Skip to content

set_eip1559_fees sets maxFeePerGas without base fee headroom, so transactions are rejected when the base fee rises #2765

Description

@aelmanaa

Describe the bug
EthereumClient.set_eip1559_fees (and AsyncEthereumClient.async_set_eip1559_fees) set maxFeePerGas = base_fee + max_priority_fee, with no headroom over the estimated next-block base fee (safe_eth/eth/ethereum_client.py:1956). If the base fee rises before the transaction is mined, which it can by up to 12.5% per block, the node rejects it with max fee per gas less than block base fee.

This is what makes safe-cli fail to execute transactions (safe_tx.execute(..., eip1559_speed=TxSpeed.NORMAL) → web3.exceptions.Web3RPCError: 'max fee per gas less than block base fee'), as previously reported in safe-global/safe-cli#104 and safe-global/safe-cli#362; we hit it with safe-cli 1.9.0 on Sepolia.

To Reproduce
With anvil --port 8546 --base-fee 1000000000:

from eth_account import Account
from safe_eth.eth import EthereumClient
from safe_eth.eth.ethereum_client import TxSpeed

client = EthereumClient("http://127.0.0.1:8546")
w3 = client.w3
account = Account.from_key("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")  # anvil test account
tx = client.set_eip1559_fees({"from": account.address, "to": Account.create().address, "value": 1,
                              "gas": 21000, "nonce": w3.eth.get_transaction_count(account.address)})
base, _ = client.estimate_fee_eip1559(TxSpeed.NORMAL)
w3.provider.make_request("anvil_setNextBlockBaseFeePerGas", [hex(base * 9 // 8 + 1)])  # one block's max rise
w3.eth.send_raw_transaction(account.sign_transaction(tx).raw_transaction)

Output on main (416a252):

estimated base fee 1000000000 wei -> maxFeePerGas 1000000000 (priority 0)
next block base fee rises one block's max to 1125000001 wei
{'code': -32003, 'message': 'max fee per gas less than block base fee'}

Expected behavior
maxFeePerGas leaves headroom for the base fee to rise, as web3.py does when it fills EIP-1559 fees (maxPriorityFeePerGas + 2 * baseFeePerGas, web3/_utils/transactions.py). Only the actual base fee is charged, so the headroom does not increase the cost.

Additional context
I have a fix (sync and async clients) with tests and will open a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions