2

According to the docs a non matching function identifier will trigger the fallback function. So what happens if someone calls my contract with "thisMethodDoesntExist()", would the fallback have a limit of 2300 like when it is triggered with send / transfer, or will it have gas from by the calling method like .call.value?

2

Surprisingly no, and the official documentation is indeed not even clear about this.

So here is a short test for printing the gas remaining at the beginning of the fallback function:

Solidity Contract:

pragma solidity 0.6.12;

interface Interface0 {
    function thisMethodDoesntExist() external;
}

contract Contract1 {
    // note that prior to solidity 0.6.0, you need to replace `fallback` with `function`
    fallback() external payable {
        string memory message;
        uint256 x = gasleft();
        while (x > 0) {
            message = string(abi.encodePacked(uint8(x % 10 + 48), message));
            x /= 10;
        }
        revert(message);
    }
}

contract Contract2 {
    function test(Interface0 contract1) external {
        contract1.thisMethodDoesntExist();
    }
}

Truffle 5.x Test:

const Contract1 = artifacts.require("Contract1");
const Contract2 = artifacts.require("Contract2");

contract("test", (accounts) => {
    it("test", async () => {
        contract1 = await Contract1.new();
        contract2 = await Contract2.new();
        try {
            await contract2.test(contract1.address);
        }
        catch (error) {
            console.log(error.message);
        }
    });
});

The printout of this test is:

VM Exception while processing transaction: revert 9328773 -- Reason given: 9328773
4
  • 1
    I don't see how this would be a big problem. If I call a method which doesn't exist the fallback is called instead with the original gas stipend. Obviously this is probably not what the user intended, but I don't see any better alternative either - it's good to have some way to catch arbitrary (wrong) function calls. Nov 15 '20 at 15:00
  • @LauriPeltonen: Thank you for the feedback! Nov 15 '20 at 15:07
  • The conclusions are correct, gas stipend is enforced by the caller.
    – Ismael
    Nov 16 '20 at 6:11
  • @Ismael: Thank you for the feedback! Coming to think about this again, maybe it's not that much of a surprise. The 2300 stipend is designated to protect your own contract from reentrancy attacks when you execute transfer or send from a function in that contract, not when you execute some non-existing function. In other words, you should know what you're doing, and executing transfer or send goes under the category of knowing what you're doing (while executing some non-existing function doesn't). Nov 16 '20 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.