I'm working with an standard ERC20 token, I have a transfer function:
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
I have an address A that has 20 of my ERC20 tokens, and I'm using web3.js to send transactions to a smart contract that is deployed on a Geth private node. MetaMask is intercepting those invocations.
I'm curious about the behaviour of MetaMask in these two scenarios:
Send 19 tokens from address A to adddress B, the transaction succeeds, now A has 1 token
Try to send 21 tokens from address A to address B, metamask shows this message:
It is as if MetaMask knows that the precondition of the contract will fail:
require(_value <= balances[msg.sender]);
I'm curious to know if MetaMask has its own state of the contract and can determine if a transaction will fail or not, previous to invoking the contract, or while it is invoking the contract.

eth_estimateGason the Ethereum node it's talking to. This does much the same thing aseth_call... it executes the transaction locally to measure the gas usage and then just throws away the side effects. – user19510 Jun 27 '18 at 15:25