I have tested a contract having a fallback function which updated a state variable (cost 5000 gas). I sent an amount of Ether to this contract with 100000 gas limit. The transaction is valid. As explained in solidity considerations, it should be fail because gas stipend is 2300. Can someone help me explain?
[Ethereum] Execution of Fallback function with more 2300 gas
fallback-functiongasgas-limitsolidity
Related Solutions
The fallback function is just like any other function: it gets as much gas as you pass to it.
What's different about the fallback function is that it's the one invoked when someone does a simple ether transfer, e.g. msg.sender.transfer(amount)
in a smart contract, or a transfer from an exchange, etc. In those cases, very little gas is sent along, so if you want those cases to succeed, you should be careful about what you put in the fallback function.
I think there are other reasons to avoid the fallback function, notably around helping to prevent mistakes. See https://programtheblockchain.com/posts/2017/12/16/be-careful-when-using-the-solidity-fallback-function/.
What is the meaning of stipend if transactions are always have gas limit set by sender?
Not really. When EOA calls contract A, the gas limit is set in the transaction, this is true. However, when contract A calls contract B, contract A may set limit on how much gas the contract B is allowed to spend. This limit may be lower than the remaining gas contract A has by itself at the moment. In such case, even if call to contract B will run out of gas and thus fail, contract A will still have some gas to handle the situation.
When, in what cases, does this damn 'stipend' apply?
There are several ways how one contract may call another contract, and these ways behave differently:
- One may just call other contract's method as a function. In this case called contract will be allowed to spend all the gas remaining in the transaction.
- One may use functions
call
,delegatecall
, orstaticall
that allow explicitly specifying how much gas to called contract will be allowed to spend (though by default these functions allow spending all the gas remaining). - One may use functions
transfer
ofsend
that allow called contract to spend at most 2300 gas, and this hardcoded value cannot be changed.
Could someone please provide a piece of code or describe a scenario when 2300 stipend is not enough?
Sure. Lets assume the following implementation of contract B:
contractB {
uint private etherReceived = 0;
function () external payable {
etherReceived += msg.value;
}
}
The contract tries to count how much Ether it ever received via fallback function. This implementation has a problem, as it updates storage variable inside fallback function and such update costs 5000 gas or more. Thus, transfer
to such contract from another contract will fail.
Could someone please provide a piece of code or describe a scenario when ... we set gasLimit which is enough to execute transfer function?
Function transfer
has hardcoded gas limit of 2300 which cannot be changed. However here is an example of a contract whose fallback function fits into this harsh limit and yet does something useful:
contractB {
event Deposit (address from, uint value);
function () external payable {
emit Deposit (msg.sender, msg.value);
}
}
Best Answer
I was confused by this questions and self answer, so I will try to clarify.
The OP sent 1,000,000 gas to a smart contract from an external account. He/she incorrectly read the Solidity documentation to say that there was a 'stipend' of only 2300 gas on such a transaction, but that was mistaken.
The 'stipend' applies to internal
sends
from one smart contract to another. Becausesend
has no way to specify the gas amount, (whereascall
does), Solidity imposes a maximum amount of gas (i.e. 2300).Because the OP's transaction was not an internal contract-to-contract
send
the 2300 stipend did not apply and the transaction went through.