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
?
1 Answer
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
-
1I 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, 2020 at 15:00
-
-
-
1@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
orsend
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 executingtransfer
orsend
goes under the category of knowing what you're doing (while executing some non-existing function doesn't). Nov 16, 2020 at 7:31