Intro
Every CALL within a transaction which sends ETH in the EVM (value > 0) costs 6700 more than the equivalent valueless CALL would. Intuitively the basic reasoning seems to be that:
Sending value along with a call incurs some additional overhead because it modifies the recipient’s balance and therefore requires an update of the node and the state trie.
However similar to warm/cold storage reads it seems that for clients this added overhead is constant in practice, in the sense that multiple value-sending CALLs to/from the same addresses within a transaction will only require 1 state-trie-node update per account. The unique overhead for a balance change is even less if the account’s state-trie-node already needs to be updated for other reasons like. a storage root change or code change.
Overview
I’d like to open the discussion around the introduction of a new EIP that’ll introduce cold/warm gas cost dynamics for account balances similar to that of storage slots or accounts themself.
Motivation
The 6700 gas value-bearing-CALL stipend places quite a heavy burden on smart contract wallets such as those working with the ERC-4337 standard as they have to execute multiple payable-CALLs per transaction and do so to accounts who’s balance is already being changed in the transaction.
Pricing CALL more fairly will make smart contract wallets cheaper and more accessible.
Rough Proposal
- In every transaction maintain a new set of addresses called
warm_account_balances - At the start of every transaction the
fromaddress is added to thewarm_account_balancesset, the transaction’stoaddress is also added if the transaction’s value is non-zero - Whenever a
CALLwithvalue > 0is made:- If both the caller and call-target are already in
warm_account_balancesno added costinstead of +6,700 - If only one of two are in
warm_account_balancesadd +3,350 to the cost of theCALL - If neither are in the
warm_account_balancesset add the existing +6,700 cost - Add any address that’s part of the call and not in
warm_account_balancesto the set
- If both the caller and call-target are already in
- If a
CALLthat added addresses to thewarm_account_balancesreverts remove the added addresses from the set
This logic could be made more complex to account for storage root changes and reduce CALLs cost there as well but for the sake of implementation simplicity it may be best to leave it like this.
Feedback & Discussion
Is there some overlooked complexity and overhead that needs to be done upon every value-bearing call? Should it really cost an added +6,700 gas (for reference that’s equivalent to a cold storage slot change +1,700) when it’s just a trie-node update too?