diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index f769b2f06254..1d34bf578ebe 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -2991,6 +2991,26 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "blobhashes", + "description": "Sets the blobhashes in the transaction.\nNot available on EVM versions before Cancun.\nIf used on unsupported EVM versions it will revert.", + "declaration": "function blobhashes(bytes32[] calldata blobhashes) external;", + "visibility": "external", + "mutability": "", + "signature": "blobhashes(bytes32[])", + "selector": "0x129de7eb", + "selectorBytes": [ + 18, + 157, + 231, + 235 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "breakpoint_0", @@ -4711,6 +4731,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "getBlobhashes", + "description": "Gets the blockhashes from the current transaction.\nNot available on EVM versions before Cancun.\nIf used on unsupported EVM versions it will revert.", + "declaration": "function getBlobhashes() external view returns (bytes32[] memory blobhashes);", + "visibility": "external", + "mutability": "view", + "signature": "getBlobhashes()", + "selector": "0xf56ff18b", + "selectorBytes": [ + 245, + 111, + 241, + 139 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "getBlockNumber", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index e838298c73eb..a62a05880f27 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -381,6 +381,18 @@ interface Vm { #[cheatcode(group = Evm, safety = Unsafe)] function prevrandao(uint256 newPrevrandao) external; + /// Sets the blobhashes in the transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + #[cheatcode(group = Evm, safety = Unsafe)] + function blobhashes(bytes32[] calldata blobhashes) external; + + /// Gets the blockhashes from the current transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + #[cheatcode(group = Evm, safety = Unsafe)] + function getBlobhashes() external view returns (bytes32[] memory blobhashes); + /// Sets `block.height`. #[cheatcode(group = Evm, safety = Unsafe)] function roll(uint256 newHeight) external; diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index bfe43d6849aa..c924c243629f 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -303,6 +303,31 @@ impl Cheatcode for prevrandao_1Call { } } +impl Cheatcode for blobhashesCall { + fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { blobhashes } = self; + ensure!( + ccx.ecx.spec_id() >= SpecId::CANCUN, + "`blobhash` is not supported before the Cancun hard fork; \ + see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" + ); + ccx.ecx.env.tx.blob_hashes.clone_from(blobhashes); + Ok(Default::default()) + } +} + +impl Cheatcode for getBlobhashesCall { + fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { + let Self {} = self; + ensure!( + ccx.ecx.spec_id() >= SpecId::CANCUN, + "`blobhash` is not supported before the Cancun hard fork; \ + see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" + ); + Ok(ccx.ecx.env.tx.blob_hashes.clone().abi_encode()) + } +} + impl Cheatcode for rollCall { fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newHeight } = self; diff --git a/testdata/cancun/cheats/Blobhashes.t.sol b/testdata/cancun/cheats/Blobhashes.t.sol new file mode 100644 index 000000000000..4a589b45a38f --- /dev/null +++ b/testdata/cancun/cheats/Blobhashes.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.25; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +contract BlobhashesTest is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testSetAndGetBlobhashes() public { + bytes32[] memory blobhashes = new bytes32[](2); + blobhashes[0] = bytes32(0x0000000000000000000000000000000000000000000000000000000000000001); + blobhashes[1] = bytes32(0x0000000000000000000000000000000000000000000000000000000000000002); + vm.blobhashes(blobhashes); + + bytes32[] memory gotBlobhashes = vm.getBlobhashes(); + assertEq(gotBlobhashes[0], blobhashes[0]); + assertEq(gotBlobhashes[1], blobhashes[1]); + } +} diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 854f57d23f51..e70049cbf8f3 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -145,6 +145,7 @@ interface Vm { function assertTrue(bool condition, string calldata error) external pure; function assume(bool condition) external pure; function blobBaseFee(uint256 newBlobBaseFee) external; + function blobhashes(bytes32[] calldata blobhashes) external; function breakpoint(string calldata char) external; function breakpoint(string calldata char, bool value) external; function broadcast() external; @@ -231,6 +232,7 @@ interface Vm { function ffi(string[] calldata commandInput) external returns (bytes memory result); function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); function getBlobBaseFee() external view returns (uint256 blobBaseFee); + function getBlobhashes() external view returns (bytes32[] memory blobhashes); function getBlockNumber() external view returns (uint256 height); function getBlockTimestamp() external view returns (uint256 timestamp); function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);