Search code examples
ethereumsolidity

Why is called revert?


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;



contract ExchangeTest {
   address owner;
   address addr;
   mapping(address => uint256) balancesToken;

   constructor() {
       owner = msg.sender;
       addr = address(this);
   }

   function EthToToken() public payable {
       balancesToken[msg.sender] += msg.value;
   }

   function TokenToEth(uint256 val) public payable {
       require(addr.balance >= val, "Not enougt eth");
       require(msg.sender == owner, "Not a round");
       address sender = msg.sender;
       balancesToken[sender] -= val;
       payable(sender).transfer(val);
   }
}

VM Exception while processing transaction: revert

Maybe this is due to the fact that I transfer and withdraw funds for the contract not directly, but through another contract? I also call contracts with web3.py.


Solution

  • Apart from edge cases such as not enough gas sent with the transaction or hitting the block gas limit, TokenToEth() can revert for multiple reasons:

    1. require(addr.balance >= val, "Not enougt eth");

      Native balance of addr is lower than the value of val passed to the function.

    2. require(msg.sender == owner, "Not a round");

      You're invoking the function from a different address than the owner (effectively the contract deployer).

    3. balancesToken[sender] -= val;

      Integer underflow. Solidity 0.8 throws an exception if you're trying to subtract a larger number from a smaller one and store this value in an uint type (unsigned integer - no negative numbers). E.g. if you're trying to calculate "one minus two".

    4. payable(sender).transfer(val);

      If sender is a contract, it needs to implement either the receive() or fallback() special functions and not throw an exception while executing the function - otherwise it rejects the transfer.