ApeWorX / ape-foundry

Foundry network provider for the Ape Framework
https://www.apeworx.io/
Apache License 2.0
33 stars 13 forks source link

`provider.reset_fork` does not reset base fee #31

Closed fmrmf closed 1 year ago

fmrmf commented 1 year ago

Environment information

$ ape --version
0.5.9

$ ape plugins list
Installed Plugins:
  vyper        0.5.2
  solidity     0.5.4
  notebook     0.5.0a2
  alchemy      0.5.4
  etherscan    0.5.5
  foundry      0.5.2
  risk         0.1.0a2

What went wrong?

Looking to use the provider reset_fork(block_number: Optional[int]) function to programmatically reset the forked chain to a specified block number (i.e. not by specifying fork block number in ape-config.yaml).

When attempting to do this as in backtest_ape/base.py#L181, found the block.base_fee for the next mined block will be set as the base fee from the initial fork block number specified in the ape-config.yaml file, instead of the base fee for the new block_number looking to reset to.

This can lead to transactions that would have been included in the first block after the reset fork number not being re-included post fork with the error

VirtualMachineError: max fee per gas less than block base fee

From console:

$ ape console

INFO: Starting 'anvil' process.

In [1]: chain.blocks.head
Out[1]: Block(num_transactions=156, hash=HexBytes('0x1d4aca1bb3bd1ffca134d8ee321e7
f2acde5079ecfa12f35e57300a4beea6989'), number=16557788, parent_hash=HexBytes('0x65
d81b43a938bc515d0597938adfc319bca3b15a851e2afdc42fa94888b2ec85'), size=172990, tim
estamp=1675542299, gas_limit=30000000, gas_used=20573012, base_fee=23076701240, di
fficulty=0, total_difficulty=58750003716598352816469)

In [2]: start = 16048833

In [3]: chain.provider.reset_fork(start)

In [4]: chain.blocks.head
Out[4]: Block(num_transactions=153, hash=HexBytes('0xfd862789eddf413de6f6b7738a335
8cb1c1da182ba50593b21ae30b50fafb9fb'), number=16048833, parent_hash=HexBytes('0x42
6a71fce2d772015a56ce1086d7d688b45fdfee9c243355221f01f57d3cedc3'), size=66789, time
stamp=1669401467, gas_limit=30000000, gas_used=12830390, base_fee=9271428794, diff
iculty=0, total_difficulty=58750003716598352816469)

In [5]: chain.blocks.head.number
Out[5]: 16048833

In [6]: chain.mine()

In [7]: chain.blocks.head
Out[7]: Block(num_transactions=0, hash=HexBytes('0x5451144127ca3ffad8a5d3c037ce471a760894ffa0250cf825b3725291e21ec1'), number=16048834, parent_hash=HexBytes('0xfd862789eddf413de6f6b7738a3358cb1c1da182ba50593b21ae30b50fafb9fb'), size=518, timestamp=1669401485, gas_limit=30000000, gas_used=0, base_fee=23076701240, difficulty=0, total_difficulty=58750003716598352816469)

In [8]: chain.blocks.head.number
Out[8]: 16048834

In [9]: chain.blocks.head.base_fee
Out[9]: 23076701240

In [10]: chain.blocks[-1].base_fee
Out[10]: 23076701240

In [11]: chain.blocks[-2].base_fee
Out[11]: 9271428794

In [12]: chain.blocks[-2].base_fee / chain.blocks[-1].base_fee
Out[12]: 0.4017657765542923

In [13]: chain.provider.reset_fork(16557788)

In [14]: chain.blocks.head
Out[14]: Block(num_transactions=156, hash=HexBytes('0x1d4aca1bb3bd1ffca134d8ee321e7f2acde5079ecfa12f35e57300a4beea6989'), number=16557788, parent_hash=HexBytes('0x65d81b43a938bc515d0597938adfc319bca3b15a851e2afdc42fa94888b2ec85'), size=172990, timestamp=1675542299, gas_limit=30000000, gas_used=20573012, base_fee=23076701240, difficulty=0, total_difficulty=58750003716598352816469)

In [15]: chain.blocks.head.base_fee
Out[15]: 23076701240

How can it be fixed?

The bug can be fixed by calling the setNextBlockBaseFeePerGas endpoint using the base fee fetched from the new chain.blocks.head post-reset as done here.

There's likely a way to avoid two calls by passing in a new value for the initialBaseFeePerGas param to the anvil_reset endpoint, but wasn't able to get that to work properly.

antazoey commented 1 year ago

Good catch! Feel free to open a PR with either approach. 2 requests is not a big deal here I don't think.

fmrmf commented 1 year ago

Sounds good! Believe this also applies to ape-hardhat for the same function. Will make a PR there too if that works.