Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Error "sender account not recognized" when sending a transaction from the zero address #4187

Closed
Morinohtar opened this issue Jul 15, 2021 · 7 comments

Comments

@Morinohtar
Copy link

Morinohtar commented Jul 15, 2021

Issue

I built a BEP20 contract.

I'm doing a simple test to check that the sender is not the zero address when doing a transfer, and i'm getting this error in the console:

'Error: Returned error: sender account not recognized'

But when testing for the recipient as a zero address it works fine as it should.

Environment

  • Operating System: MacOS
  • Truffle v5.4.0 (core: 5.4.0)
  • Solidity - 0.8.6 (solc-js)
  • Node v14.16.0
  • Web3.js v1.4.0

Expected Behavior

It should pass the test evaluating that the return msg of the revert is:

'BEP20: transfer from the zero address'

Actual Results

The test fails and in the console it spits out this error:

'Error: Returned error: sender account not recognized'

Error pic

Code

Function triggered:

function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "BEP20: transfer from the zero address");
        require(recipient != address(0), "BEP20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "BEP20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);
    }

Tests:

            it('fails when the sender is a zero address', async () => {
                const sender = constants.ZERO_ADDRESS;
                const amount = new BN('1');

                await expectRevert(
                    token.transfer(johnDoe, amount, {from: sender}),
                    'BEP20: transfer from the zero address'
                );
            });

            it('fails when the recipient is a zero address', async () => {
                await expectRevert(
                    token.transfer(constants.ZERO_ADDRESS, new BN('1'), {from: deployer}),
                    'BEP20: transfer to the zero address'
                );
            });

Like i said before, the sender test gives the error, and the recipient test works fine.

The zero address is correct: '0x0000000000000000000000000000000000000000'

I also tried using '0x0' and got the same error.

I tried calling the method using the normal web contract construction and not using the truffle contract, like:

token.methods.transfer(johnDoe, amount).send({from: sender});

and the result was the same.

Also tried executing in the truffle console using my local ganache and got the same error.

And this happens with other functions, not just transfer, i get the same error when i use the zero address as the sender of a transaction.

I'm out of ideas at the moment, could use some help understanding this... if i got a problem here in the code or eventually this is to be expected as it is some sort of new behaviour with web3js or whatever.

Thanks.

@eggplantzzz
Copy link
Contributor

Hey @Morinohtar, can you clarify further what you expect to happen? You can't send transactions from addresses that you don't have credentials (private keys) for. You could do this if you use something like ganache-cli's -u or --unlock feature but normally you would not be able to do this. Here are some docs.

@Morinohtar
Copy link
Author

I expect what i described, it should revert with the msg i said, i can't explain more than that, dont know how to be more clear than that, sorry.

Even if i don't have the credentials of an account i can test it in some specific conditions.

I used for example a random valid address i got from the web, for which i dont have the private key or whatever, and the test ran correctly, i.e., i replaced the zero address with it and the test did what it was supposed to do.

Example:

https://bscscan.com/address/0xea3136194afd10aff63ede6bb5aab839e3baa258

I used this address for the test: 0xEA3136194afD10AfF63eDE6bB5aaB839e3Baa258

Test code:

describe('When the minter is a zero address and tries to mint to himself', () => {
    it('fails and it will not mint', async () => {
        const amount = new BN('100');

        await expectRevert(
            token.methods['mint(uint256)'](amount, {from: '0xEA3136194afD10AfF63eDE6bB5aaB839e3Baa258'}),
            'AccessControl: account 0xEA3136194afD10AfF63eDE6bB5aaB839e3Baa258 is missing role 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6'
        );
    });
});

Outcome:

Failure Path
          When the minter is a zero address and tries to mint to himself
            ✓ fails and it will not mint (154ms)

It was a success as you can see. And i used an accout for which i don't have the credentials.
I just modified the expected error msg so that it would pass.

And now the same test but with the zero address:

Test code:

describe('When the minter is a zero address and tries to mint to himself', () => {
    it('fails and it will not mint', async () => {
        const amount = new BN('100');

        await expectRevert(
            token.methods['mint(uint256)'](amount, {from: '0x0000000000000000000000000000000000000000'}),
            'BEP20: mint to the zero address'
        );
    });
});

Outcome:
'Uncaught Error: Returned error: sender account not recognized'

So, there is something special with the Zero Address when using it as the sender, and i still don't know what it is and couldnt find out.
I saw ppl testing the zero address as the sender, so i assumed it would work... Don't know if it is something that in earlier versions of Solidity/Ethereum was working and now it does not, or if it never worked, or whatever.

@Morinohtar
Copy link
Author

Morinohtar commented Jul 22, 2021

Simpler example i created for the sake of argument that also fails, just like the previous examples:

Zero Address:

Function code:

function zeroAddress() public view returns (bool) {
    require(msg.sender != address(0), 'Invalid address!');

    return true;
}

Test:

describe('When the sender is the zero address', () => {
    it('fails and reverts', async () => {
        await expectRevert(
            token.zeroAddress({from: '0x0'}),
            'Invalid address!'
        );
    });
});

The test fails!

Valid address (don't have credentials):

Function code:

function zeroAddress() public view returns (bool) {
    require(msg.sender != address(0xEA3136194afD10AfF63eDE6bB5aaB839e3Baa258), 'Invalid address!');

    return true;
}

Test:

describe('When the sender is the zero address', () => {
    it('fails and reverts', async () => {
        await expectRevert(
            token.zeroAddress({from: '0xEA3136194afD10AfF63eDE6bB5aaB839e3Baa258'}),
            'Invalid address!'
        );
    });
});

The test works!

So... if anyone knows what might be the issue here, whatever that might be, i would appreciate the insight.

@eggplantzzz
Copy link
Contributor

eggplantzzz commented Jul 22, 2021

Ah ok, I misunderstood! Actually that message is a Ganache message. For reference. When Ganache doesn't recognize the account you are sending from or if it isn't unlocked, it errors. Actually I don't think you can even get that code to run (the Solidity) because there is some kind of validation step (checking that you have the private keys) somewhere in the flow. I'm not sure where it happens exactly, probably the node verifies that you can/cannot send the transaction before it gets to the EVM. @davidmurdoch or @MicaiahReid can probably enlighten us :) Like, why would we even attempt to run the Solidity unless the tx is valid to begin with?

@Morinohtar
Copy link
Author

Morinohtar commented Jul 22, 2021

Yeap, something else must flow differently when it's the zero address.

Well, for now i have those zero address tests commented.

But since i saw some ppl using these tests i assumed they would work. The tests were using older versions of solidity, like v0.5, so maybe something changed meanwhile with the newer versions, and that's why now it's failing... go figure :) lol

@eggplantzzz
Copy link
Contributor

eggplantzzz commented Jul 22, 2021

I mean, it should be the same for all random addresses. You should get the "sender account not recognized" for every address that Ganache doesn't know about. Can you link the tests you are talking about? I'd like to take a look. Do you have an example of sending from an account that is not unlocked that sends the tx successfully?

@haltman-at
Copy link
Contributor

Closing this for isssue maintenance. Let us know if there's still a problem and we can reopen.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants