-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for the shanghai hardfork #3767
Conversation
Some changes to the test setup were also needed here because getHardforkByBlockNumber doesn't work well for Shanghai if the block's timestamp is not passed.
🦋 Changeset detectedLatest commit: fcb182d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
- london | ||
- arrowGlacier | ||
- grayGlacier |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two hardforks were missing in the list, so I just added them.
packages/hardhat-core/package.json
Outdated
"@nomicfoundation/ethereumjs-trie": "5.0.4", | ||
"@nomicfoundation/ethereumjs-tx": "4.1.1", | ||
"@nomicfoundation/ethereumjs-util": "8.0.5", | ||
"@nomicfoundation/ethereumjs-vm": "6.4.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used pinned versions this time (I should've done that the previous time). The fork also has pinned versions in their intra-dependencies.
@@ -63,7 +63,7 @@ export abstract class BlockchainBase { | |||
|
|||
public async getBlock( | |||
blockHashOrNumber: Buffer | bigint | number | |||
): Promise<Block | null> { | |||
): Promise<Block> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BlockchainInterface
has this breaking change.
if (blockByNumber === undefined) { | ||
throw new Error("Block not found"); | ||
} | ||
return blockByNumber; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now throw instead of returning null when the block doesn't exist.
@@ -48,7 +48,8 @@ export function serializeTransaction( | |||
|
|||
export function deserializeTransaction( | |||
tx: SerializedTransaction, | |||
common: Common | |||
common: Common, | |||
{ allowUnlimitedContractSize }: { allowUnlimitedContractSize: boolean } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of the changes in this PR come from the fact that we need to pass the value of allowUnlimitedContractSize
to be able to create transactions with the correct disableMaxInitCodeSizeCheck
value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a validation that is meant to be run only when receiving a new transaction, isn't it?
If that's the case we can run it in the RPC layer / Node, and use true
everywhere else. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean always using disableMaxInitCodeSizeCheck: true
, and making the max initcode check ourselves in an upper layer? Makes sense to me, I'll do that.
@@ -68,7 +72,7 @@ export class ReadOnlyValidEIP1559Transaction extends FeeMarketEIP1559Transaction | |||
} | |||
); | |||
|
|||
super(data, { freeze: false, common: fakeCommon }); | |||
super(data, { ...opts, freeze: false, common: fakeCommon }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of change is needed to pass the disableMaxInitCodeSizeCheck
flag around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -712,3 +712,38 @@ contract CallSelfDestruct { | |||
}, | |||
topics: {}, | |||
}; | |||
|
|||
export const EXAMPLE_TOUCH_ADDRESS_CONTRACT = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new example contract is used to test EIP-3651 (warm COINBASE)
assert.equal(await blockchain.getBlock(0), undefined); | ||
assert.equal(await blockchain.getBlock(randomHashBuffer()), undefined); | ||
it("throws error for non-existent block", async () => { | ||
await assert.isRejected(blockchain.getBlock(0), "Block not found"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tests changed because getBlock
now throws instead of returning null.
@@ -1532,4 +1537,289 @@ describe("Eth module - hardfork dependant tests", function () { | |||
}); | |||
}); | |||
}); | |||
|
|||
describe("shanghai hardfork", function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are the most interesting tests, please review them carefully.
]; | ||
|
||
for (const { url, blockToRun, networkName, chainId } of forkedBlocks) { | ||
const remoteCommon = new Common({ chain: chainId }); | ||
const hardfork = remoteCommon.getHardforkByBlockNumber(blockToRun); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work for shanghai because getHardforkByBlockNumber
needs the block timestamp to correctly detect that a block is in that hardfork. Now the hardfork is detected inside runFullBlock
because we have fetched the block there and can pass the timestamp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I follow this, but the rest LGTM
Adds support for the shanghai hardfork. The two main changes are:
allowUnlimitedContractSize
to work with the EIP-3860 initcode limit.withdrawals
andwithdrawalsRoot
fields to RPC blocks if Shanghai is enabled