diff --git a/packages/contracts-bedrock/lib/lib-keccak b/packages/contracts-bedrock/lib/lib-keccak index 0115edbbc60b..3b1e7bbb4cc2 160000 --- a/packages/contracts-bedrock/lib/lib-keccak +++ b/packages/contracts-bedrock/lib/lib-keccak @@ -1 +1 @@ -Subproject commit 0115edbbc60b5f702392caafc3a142061e6142fa +Subproject commit 3b1e7bbb4cc23e9228097cfebe42aedaf3b8f2b9 diff --git a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol index 153e4b65fdb4..249e526abdd8 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol @@ -321,18 +321,20 @@ contract DeployDisputeGame is Script { abi.encodeCall( IPermissionedDisputeGame.__constructor__, ( - args.gameType, - args.absolutePrestate, - args.maxGameDepth, - args.splitDepth, - args.clockExtension, - args.maxClockDuration, - args.gameVm, - args.delayedWethProxy, - args.anchorStateRegistryProxy, - args.l2ChainId, - args.proposer, - args.challenger + IPermissionedDisputeGame.PDGConstructorParams({ + _gameType: args.gameType, + _absolutePrestate: args.absolutePrestate, + _maxGameDepth: args.maxGameDepth, + _splitDepth: args.splitDepth, + _clockExtension: args.clockExtension, + _maxClockDuration: args.maxClockDuration, + _vm: args.gameVm, + _weth: args.delayedWethProxy, + _anchorStateRegistry: args.anchorStateRegistryProxy, + _l2ChainId: args.l2ChainId, + _proposer: args.proposer, + _challenger: args.challenger + }) ) ) ) diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol b/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol index 8203e42b060c..6b22314df1b3 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/DeployUpgrade.s.sol @@ -197,18 +197,20 @@ contract DeployUpgrade is Deployer { bytes memory constructorInput = abi.encodeCall( IPermissionedDisputeGame.__constructor__, ( - GameTypes.PERMISSIONED_CANNON, - Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), - cfg.faultGameMaxDepth(), - cfg.faultGameSplitDepth(), - Duration.wrap(uint64(cfg.faultGameClockExtension())), - Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - IBigStepper(mustGetAddress("MIPS")), - IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyPDG"))), - IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), - cfg.l2ChainID(), - cfg.l2OutputOracleProposer(), - cfg.l2OutputOracleChallenger() + IPermissionedDisputeGame.PDGConstructorParams({ + _gameType: GameTypes.PERMISSIONED_CANNON, + _absolutePrestate: Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())), + _maxGameDepth: cfg.faultGameMaxDepth(), + _splitDepth: cfg.faultGameSplitDepth(), + _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), + _maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + _vm: IBigStepper(mustGetAddress("MIPS")), + _weth: IDelayedWETH(payable(mustGetAddress("DelayedWETHProxyPDG"))), + _anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistry")), + _l2ChainId: cfg.l2ChainID(), + _proposer: cfg.l2OutputOracleProposer(), + _challenger: cfg.l2OutputOracleChallenger() + }) ) ); diff --git a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json index fd9737cc5842..439f01f0577c 100644 --- a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json @@ -2,64 +2,71 @@ { "inputs": [ { - "internalType": "GameType", - "name": "_gameType", - "type": "uint32" - }, - { - "internalType": "Claim", - "name": "_absolutePrestate", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_maxGameDepth", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_splitDepth", - "type": "uint256" - }, - { - "internalType": "Duration", - "name": "_clockExtension", - "type": "uint64" - }, - { - "internalType": "Duration", - "name": "_maxClockDuration", - "type": "uint64" - }, - { - "internalType": "contract IBigStepper", - "name": "_vm", - "type": "address" - }, - { - "internalType": "contract IDelayedWETH", - "name": "_weth", - "type": "address" - }, - { - "internalType": "contract IAnchorStateRegistry", - "name": "_anchorStateRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_l2ChainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_proposer", - "type": "address" - }, - { - "internalType": "address", - "name": "_challenger", - "type": "address" + "components": [ + { + "internalType": "GameType", + "name": "_gameType", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "_absolutePrestate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_maxGameDepth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_splitDepth", + "type": "uint256" + }, + { + "internalType": "Duration", + "name": "_clockExtension", + "type": "uint64" + }, + { + "internalType": "Duration", + "name": "_maxClockDuration", + "type": "uint64" + }, + { + "internalType": "contract IBigStepper", + "name": "_vm", + "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "_weth", + "type": "address" + }, + { + "internalType": "contract IAnchorStateRegistry", + "name": "_anchorStateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_proposer", + "type": "address" + }, + { + "internalType": "address", + "name": "_challenger", + "type": "address" + } + ], + "internalType": "struct PermissionedDisputeGame.PDGConstructorParams", + "name": "_params", + "type": "tuple" } ], "stateMutability": "nonpayable", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 35696bc7bf16..b3b7c16e6187 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -136,20 +136,20 @@ "sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b" }, "src/cannon/MIPS.sol": { - "initCodeHash": "0xb4aec227019dacd6194d6aeb9ca68c23c60b95618d18a4ebc09243514aeb1f05", - "sourceCodeHash": "0x4d43b3f2918486aa76d2d59ac42e4f6aa2f58538c7e95a5cb99b63c9588b5f1c" + "initCodeHash": "0xe1b9de604c61e7daad99a2eb90dfce89d605bc303df56b0a1c7ccb493fa8600d", + "sourceCodeHash": "0xf68b4fa0f7b3dbf2a0b4a4133b15eae519330471e4798e17a949d7710b68af1e" }, "src/cannon/MIPS2.sol": { - "initCodeHash": "0xe3879b5772820d837bc1c77c32a1200eb26cf901d9302dff9f0e9759331e380e", - "sourceCodeHash": "0x1c45a8f4c8c9ded7043d63965cb114d17f801c6cd4d8233cb16838c5f9a02675" + "initCodeHash": "0x22fa70f37fec4f3d3165a721abe8e2538a5fc6402fbad6ae473e9dbc55e62739", + "sourceCodeHash": "0xe7de6a02613c99ac2924bb55c34f831d0dd61fafecc8cdc0de826adf2144c709" }, "src/cannon/MIPS64.sol": { - "initCodeHash": "0xa4a761f480a26ec1926c5a8b4831440211c0441bd41d503b0aad189e030d35dc", - "sourceCodeHash": "0x7ddcf8584f9bd92abd1eb45bc198f5b0ec54acaf292f60e919d674cc56fb8abc" + "initCodeHash": "0xf5cb029be679d292f8c10ec925912c03a26e4c47b336f47aa3f36486d701b05c", + "sourceCodeHash": "0xe611d13b2a18ef011bff8c533f4e8ce7abde34cfee6817f02a0fb74193745796" }, "src/cannon/PreimageOracle.sol": { - "initCodeHash": "0x5d7e8ae64f802bd9d760e3d52c0a620bd02405dc2c8795818db9183792ffe81c", - "sourceCodeHash": "0x979d8595d925c70a123e72c062fa58c9ef94777c2e93b6bc3231d6679e2e9055" + "initCodeHash": "0x2bef439027c37c65dd8e7d9a987ff14e1dba94ee5fe5f316a77ecf46a8db4b3f", + "sourceCodeHash": "0x70965927d1cfcafa8975f3fdc98a138efe413c4a1585c0f60e0d21cfd396cc7c" }, "src/dispute/AnchorStateRegistry.sol": { "initCodeHash": "0x7bdbf9dc5125c953ea1833ccf0ad0e07d25b6f6c47e23da5374413324a38c5f9", diff --git a/packages/contracts-bedrock/src/cannon/MIPS.sol b/packages/contracts-bedrock/src/cannon/MIPS.sol index 62b3084f74a8..9fa3d8c35535 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS.sol @@ -47,8 +47,8 @@ contract MIPS is ISemver { } /// @notice The semantic version of the MIPS contract. - /// @custom:semver 1.2.1-beta.8 - string public constant version = "1.2.1-beta.8"; + /// @custom:semver 1.2.1-beta.9 + string public constant version = "1.2.1-beta.9"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; @@ -183,15 +183,17 @@ contract MIPS is ISemver { }); (v0, v1, state.preimageOffset, state.memRoot,,) = sys.handleSysRead(args); } else if (syscall_no == sys.SYS_WRITE) { - (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ - _a0: a0, - _a1: a1, - _a2: a2, - _preimageKey: state.preimageKey, - _preimageOffset: state.preimageOffset, - _proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), - _memRoot: state.memRoot - }); + (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite( + sys.SysWriteParams({ + _a0: a0, + _a1: a1, + _a2: a2, + _preimageKey: state.preimageKey, + _preimageOffset: state.preimageOffset, + _proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), + _memRoot: state.memRoot + }) + ); } else if (syscall_no == sys.SYS_FCNTL) { (v0, v1) = sys.handleSysFcntl(a0, a1); } diff --git a/packages/contracts-bedrock/src/cannon/MIPS2.sol b/packages/contracts-bedrock/src/cannon/MIPS2.sol index d28238980f38..4eaa063de724 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS2.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS2.sol @@ -63,8 +63,8 @@ contract MIPS2 is ISemver { } /// @notice The semantic version of the MIPS2 contract. - /// @custom:semver 1.0.0-beta.23 - string public constant version = "1.0.0-beta.23"; + /// @custom:semver 1.0.0-beta.24 + string public constant version = "1.0.0-beta.24"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; @@ -462,15 +462,17 @@ contract MIPS2 is ISemver { // Encapsulate execution to avoid stack-too-deep error (v0, v1) = execSysRead(state, args); } else if (syscall_no == sys.SYS_WRITE) { - (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ - _a0: a0, - _a1: a1, - _a2: a2, - _preimageKey: state.preimageKey, - _preimageOffset: state.preimageOffset, - _proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), - _memRoot: state.memRoot - }); + (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite( + sys.SysWriteParams({ + _a0: a0, + _a1: a1, + _a2: a2, + _preimageKey: state.preimageKey, + _preimageOffset: state.preimageOffset, + _proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), + _memRoot: state.memRoot + }) + ); } else if (syscall_no == sys.SYS_FCNTL) { (v0, v1) = sys.handleSysFcntl(a0, a1); } else if (syscall_no == sys.SYS_GETTID) { diff --git a/packages/contracts-bedrock/src/cannon/MIPS64.sol b/packages/contracts-bedrock/src/cannon/MIPS64.sol index bb2f4369c2a5..d0e5e28881aa 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS64.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS64.sol @@ -67,8 +67,8 @@ contract MIPS64 is ISemver { } /// @notice The semantic version of the MIPS64 contract. - /// @custom:semver 1.0.0-beta.5 - string public constant version = "1.0.0-beta.5"; + /// @custom:semver 1.0.0-beta.6 + string public constant version = "1.0.0-beta.6"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; @@ -504,15 +504,17 @@ contract MIPS64 is ISemver { // Encapsulate execution to avoid stack-too-deep error (v0, v1) = execSysRead(state, args); } else if (syscall_no == sys.SYS_WRITE) { - (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ - _a0: a0, - _a1: a1, - _a2: a2, - _preimageKey: state.preimageKey, - _preimageOffset: state.preimageOffset, - _proofOffset: MIPS64Memory.memoryProofOffset(MEM_PROOF_OFFSET, 1), - _memRoot: state.memRoot - }); + (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite( + sys.SysWriteParams({ + _a0: a0, + _a1: a1, + _a2: a2, + _preimageKey: state.preimageKey, + _preimageOffset: state.preimageOffset, + _proofOffset: MIPS64Memory.memoryProofOffset(MEM_PROOF_OFFSET, 1), + _memRoot: state.memRoot + }) + ); } else if (syscall_no == sys.SYS_FCNTL) { (v0, v1) = sys.handleSysFcntl(a0, a1); } else if (syscall_no == sys.SYS_GETTID) { diff --git a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol index 7ac7c33d99d2..03c0b3ae5521 100644 --- a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol @@ -51,8 +51,8 @@ contract PreimageOracle is ISemver { uint256 public constant PRECOMPILE_CALL_RESERVED_GAS = 100_000; /// @notice The semantic version of the Preimage Oracle contract. - /// @custom:semver 1.1.3-beta.6 - string public constant version = "1.1.3-beta.6"; + /// @custom:semver 1.1.3-beta.7 + string public constant version = "1.1.3-beta.7"; //////////////////////////////////////////////////////////////// // Authorized Preimage Parts // diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol index d4b706da4b59..2ed0976de4ed 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol @@ -308,27 +308,29 @@ library MIPS64Syscalls { } } + /// @custom:field _a0 The file descriptor. + /// @custom:field _a1 The memory address to read from. + /// @custom:field _a2 The number of bytes to read. + /// @custom:field _preimageKey The current preimaageKey. + /// @custom:field _preimageOffset The current preimageOffset. + /// @custom:field _proofOffset The offset of the memory proof in calldata. + /// @custom:field _memRoot The current memory root. + struct SysWriteParams { + uint64 _a0; + uint64 _a1; + uint64 _a2; + bytes32 _preimageKey; + uint64 _preimageOffset; + uint256 _proofOffset; + bytes32 _memRoot; + } + /// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes. - /// @param _a0 The file descriptor. - /// @param _a1 The memory address to read from. - /// @param _a2 The number of bytes to read. - /// @param _preimageKey The current preimaageKey. - /// @param _preimageOffset The current preimageOffset. - /// @param _proofOffset The offset of the memory proof in calldata. - /// @param _memRoot The current memory root. /// @return v0_ The number of bytes written, or -1 on error. /// @return v1_ The error code, or 0 if empty. /// @return newPreimageKey_ The new preimageKey. /// @return newPreimageOffset_ The new preimageOffset. - function handleSysWrite( - uint64 _a0, - uint64 _a1, - uint64 _a2, - bytes32 _preimageKey, - uint64 _preimageOffset, - uint256 _proofOffset, - bytes32 _memRoot - ) + function handleSysWrite(SysWriteParams memory _args) internal pure returns (uint64 v0_, uint64 v1_, bytes32 newPreimageKey_, uint64 newPreimageOffset_) @@ -338,20 +340,22 @@ library MIPS64Syscalls { // returns: v0_ = written, v1_ = err code v0_ = uint64(0); v1_ = uint64(0); - newPreimageKey_ = _preimageKey; - newPreimageOffset_ = _preimageOffset; + newPreimageKey_ = _args._preimageKey; + newPreimageOffset_ = _args._preimageOffset; - if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) { - v0_ = _a2; // tell program we have written everything + if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) { + v0_ = _args._a2; // tell program we have written everything } // pre-image oracle - else if (_a0 == FD_PREIMAGE_WRITE) { + else if (_args._a0 == FD_PREIMAGE_WRITE) { // mask the addr to align it to 4 bytes - uint64 mem = MIPS64Memory.readMem(_memRoot, _a1 & arch.ADDRESS_MASK, _proofOffset); - bytes32 key = _preimageKey; + uint64 mem = MIPS64Memory.readMem(_args._memRoot, _args._a1 & arch.ADDRESS_MASK, _args._proofOffset); + bytes32 key = _args._preimageKey; // Construct pre-image key from memory // We use assembly for more precise ops, and no var count limit + uint64 _a1 = _args._a1; + uint64 _a2 = _args._a2; assembly { let alignment := and(_a1, EXT_MASK) // the read might not start at an aligned address let space := sub(WORD_SIZE_BYTES, alignment) // remaining space in memory word @@ -361,11 +365,12 @@ library MIPS64Syscalls { mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it key := or(key, mem) // insert into key } + _args._a2 = _a2; // Write pre-image key to oracle newPreimageKey_ = key; newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start - v0_ = _a2; + v0_ = _args._a2; } else { v0_ = U64_MASK; v1_ = EBADF; diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol index 8e3516c0c1e5..bb94865b3598 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol @@ -298,27 +298,29 @@ library MIPSSyscalls { } } + /// @custom:field _a0 The file descriptor. + /// @custom:field _a1 The memory address to read from. + /// @custom:field _a2 The number of bytes to read. + /// @custom:field _preimageKey The current preimaageKey. + /// @custom:field _preimageOffset The current preimageOffset. + /// @custom:field _proofOffset The offset of the memory proof in calldata. + /// @custom:field _memRoot The current memory root. + struct SysWriteParams { + uint32 _a0; + uint32 _a1; + uint32 _a2; + bytes32 _preimageKey; + uint32 _preimageOffset; + uint256 _proofOffset; + bytes32 _memRoot; + } + /// @notice Like a Linux write syscall. Splits unaligned writes into aligned writes. - /// @param _a0 The file descriptor. - /// @param _a1 The memory address to read from. - /// @param _a2 The number of bytes to read. - /// @param _preimageKey The current preimaageKey. - /// @param _preimageOffset The current preimageOffset. - /// @param _proofOffset The offset of the memory proof in calldata. - /// @param _memRoot The current memory root. /// @return v0_ The number of bytes written, or -1 on error. /// @return v1_ The error code, or 0 if empty. /// @return newPreimageKey_ The new preimageKey. /// @return newPreimageOffset_ The new preimageOffset. - function handleSysWrite( - uint32 _a0, - uint32 _a1, - uint32 _a2, - bytes32 _preimageKey, - uint32 _preimageOffset, - uint256 _proofOffset, - bytes32 _memRoot - ) + function handleSysWrite(SysWriteParams memory _args) internal pure returns (uint32 v0_, uint32 v1_, bytes32 newPreimageKey_, uint32 newPreimageOffset_) @@ -328,20 +330,22 @@ library MIPSSyscalls { // returns: v0_ = written, v1_ = err code v0_ = uint32(0); v1_ = uint32(0); - newPreimageKey_ = _preimageKey; - newPreimageOffset_ = _preimageOffset; + newPreimageKey_ = _args._preimageKey; + newPreimageOffset_ = _args._preimageOffset; - if (_a0 == FD_STDOUT || _a0 == FD_STDERR || _a0 == FD_HINT_WRITE) { - v0_ = _a2; // tell program we have written everything + if (_args._a0 == FD_STDOUT || _args._a0 == FD_STDERR || _args._a0 == FD_HINT_WRITE) { + v0_ = _args._a2; // tell program we have written everything } // pre-image oracle - else if (_a0 == FD_PREIMAGE_WRITE) { + else if (_args._a0 == FD_PREIMAGE_WRITE) { // mask the addr to align it to 4 bytes - uint32 mem = MIPSMemory.readMem(_memRoot, _a1 & 0xFFffFFfc, _proofOffset); - bytes32 key = _preimageKey; + uint32 mem = MIPSMemory.readMem(_args._memRoot, _args._a1 & 0xFFffFFfc, _args._proofOffset); + bytes32 key = _args._preimageKey; // Construct pre-image key from memory // We use assembly for more precise ops, and no var count limit + uint32 _a1 = _args._a1; + uint32 _a2 = _args._a2; assembly { let alignment := and(_a1, 3) // the read might not start at an aligned address let space := sub(4, alignment) // remaining space in memory word @@ -351,11 +355,12 @@ library MIPSSyscalls { mem := and(shr(mul(sub(space, _a2), 8), mem), mask) // align value to right, mask it key := or(key, mem) // insert into key } + _args._a2 = _a2; // Write pre-image key to oracle newPreimageKey_ = key; newPreimageOffset_ = 0; // reset offset, to read new pre-image data from the start - v0_ = _a2; + v0_ = _args._a2; } else { v0_ = 0xFFffFFff; v1_ = EBADF; diff --git a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol index 373498f55bfa..645b757d90dd 100644 --- a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol @@ -22,6 +22,34 @@ import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; /// costs that certain networks may not wish to support. This contract can also be used as a fallback mechanism /// in case of a failure in the permissionless fault proof system in the stage one release. contract PermissionedDisputeGame is FaultDisputeGame { + /// @custom:field _gameType The type ID of the game. + /// @custom:field _absolutePrestate The absolute prestate of the instruction trace. + /// @custom:field _maxGameDepth The maximum depth of bisection. + /// @custom:field _splitDepth The final depth of the output bisection portion of the game. + /// @custom:field _clockExtension The clock extension to perform when the remaining duration is less than the + /// extension. + /// @custom:field _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock. + /// @custom:field _vm An onchain VM that performs single instruction steps on an FPP trace. + /// @custom:field _weth WETH contract for holding ETH. + /// @custom:field _anchorStateRegistry The contract that stores the anchor state for each game type. + /// @custom:field _l2ChainId Chain ID of the L2 network this contract argues about. + /// @custom:field _proposer Address that is allowed to create instances of this contract. + /// @custom:field _challenger Address that is allowed to challenge instances of this contract. + struct PDGConstructorParams { + GameType _gameType; + Claim _absolutePrestate; + uint256 _maxGameDepth; + uint256 _splitDepth; + Duration _clockExtension; + Duration _maxClockDuration; + IBigStepper _vm; + IDelayedWETH _weth; + IAnchorStateRegistry _anchorStateRegistry; + uint256 _l2ChainId; + address _proposer; + address _challenger; + } + /// @notice The proposer role is allowed to create proposals and participate in the dispute game. address internal immutable PROPOSER; @@ -36,47 +64,22 @@ contract PermissionedDisputeGame is FaultDisputeGame { _; } - /// @param _gameType The type ID of the game. - /// @param _absolutePrestate The absolute prestate of the instruction trace. - /// @param _maxGameDepth The maximum depth of bisection. - /// @param _splitDepth The final depth of the output bisection portion of the game. - /// @param _clockExtension The clock extension to perform when the remaining duration is less than the extension. - /// @param _maxClockDuration The maximum amount of time that may accumulate on a team's chess clock. - /// @param _vm An onchain VM that performs single instruction steps on an FPP trace. - /// @param _weth WETH contract for holding ETH. - /// @param _anchorStateRegistry The contract that stores the anchor state for each game type. - /// @param _l2ChainId Chain ID of the L2 network this contract argues about. - /// @param _proposer Address that is allowed to create instances of this contract. - /// @param _challenger Address that is allowed to challenge instances of this contract. - constructor( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId, - address _proposer, - address _challenger - ) + constructor(PDGConstructorParams memory _params) FaultDisputeGame( - _gameType, - _absolutePrestate, - _maxGameDepth, - _splitDepth, - _clockExtension, - _maxClockDuration, - _vm, - _weth, - _anchorStateRegistry, - _l2ChainId + _params._gameType, + _params._absolutePrestate, + _params._maxGameDepth, + _params._splitDepth, + _params._clockExtension, + _params._maxClockDuration, + _params._vm, + _params._weth, + _params._anchorStateRegistry, + _params._l2ChainId ) { - PROPOSER = _proposer; - CHALLENGER = _challenger; + PROPOSER = _params._proposer; + CHALLENGER = _params._challenger; } /// @inheritdoc FaultDisputeGame diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol index c5a5a187ec12..4f4b021aaf5e 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol @@ -10,6 +10,21 @@ import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; interface IPermissionedDisputeGame is IDisputeGame { + struct PDGConstructorParams { + GameType _gameType; + Claim _absolutePrestate; + uint256 _maxGameDepth; + uint256 _splitDepth; + Duration _clockExtension; + Duration _maxClockDuration; + IBigStepper _vm; + IDelayedWETH _weth; + IAnchorStateRegistry _anchorStateRegistry; + uint256 _l2ChainId; + address _proposer; + address _challenger; + } + struct ClaimData { uint32 parentIndex; address counteredBy; @@ -119,19 +134,5 @@ interface IPermissionedDisputeGame is IDisputeGame { function proposer() external view returns (address proposer_); function challenger() external view returns (address challenger_); - function __constructor__( - GameType _gameType, - Claim _absolutePrestate, - uint256 _maxGameDepth, - uint256 _splitDepth, - Duration _clockExtension, - Duration _maxClockDuration, - IBigStepper _vm, - IDelayedWETH _weth, - IAnchorStateRegistry _anchorStateRegistry, - uint256 _l2ChainId, - address _proposer, - address _challenger - ) - external; + function __constructor__(PDGConstructorParams memory _params) external; } diff --git a/packages/contracts-bedrock/test/cannon/MIPS2.t.sol b/packages/contracts-bedrock/test/cannon/MIPS2.t.sol index 2cc0519ea5bf..d38ab89ff556 100644 --- a/packages/contracts-bedrock/test/cannon/MIPS2.t.sol +++ b/packages/contracts-bedrock/test/cannon/MIPS2.t.sol @@ -789,8 +789,9 @@ contract MIPS2_Test is CommonTest { vm.expectRevert(InvalidMemoryProof.selector); mips.step(encodeState(state), bytes.concat(threadWitness, invalidInsnAndMemProof, memProof2), 0); - (, bytes memory invalidMemProof2) = - ffi.getCannonMemoryProof2(pc, insn, timespecAddr, secs + 1, timespecAddr + 4); + uint32 _secs = secs + 1; + uint32 _timespecAddr = timespecAddr + 4; + (, bytes memory invalidMemProof2) = ffi.getCannonMemoryProof2(pc, insn, timespecAddr, _secs, _timespecAddr); vm.expectRevert(InvalidSecondMemoryProof.selector); mips.step(encodeState(state), bytes.concat(threadWitness, insnAndMemProof, invalidMemProof2), 0); } @@ -2766,31 +2767,21 @@ contract MIPS2_Test is CommonTest { } function encodeState(IMIPS2.State memory _state) internal pure returns (bytes memory) { - // Split up encoding to get around stack-too-deep error - return abi.encodePacked(encodeStateA(_state), encodeStateB(_state)); - } - - function encodeStateA(IMIPS2.State memory _state) internal pure returns (bytes memory) { - return abi.encodePacked( + bytes memory a = abi.encodePacked( _state.memRoot, _state.preimageKey, _state.preimageOffset, _state.heap, _state.llReservationStatus, - _state.llAddress, - _state.llOwnerThread, - _state.exitCode, - _state.exited, - _state.step, - _state.stepsSinceLastContextSwitch, - _state.wakeup, - _state.traverseRight, - _state.leftThreadStack + _state.llAddress ); - } - - function encodeStateB(IMIPS2.State memory _state) internal pure returns (bytes memory) { - return abi.encodePacked(_state.rightThreadStack, _state.nextThreadID); + bytes memory b = abi.encodePacked( + _state.llOwnerThread, _state.exitCode, _state.exited, _state.step, _state.stepsSinceLastContextSwitch + ); + bytes memory c = abi.encodePacked( + _state.wakeup, _state.traverseRight, _state.leftThreadStack, _state.rightThreadStack, _state.nextThreadID + ); + return abi.encodePacked(a, b, c); } function copyState(IMIPS2.State memory _state) internal pure returns (IMIPS2.State memory out_) { diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 99b70b9c6dff..29718cec3d85 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -67,18 +67,20 @@ contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { abi.encodeCall( IPermissionedDisputeGame.__constructor__, ( - GAME_TYPE, - absolutePrestate, - 2 ** 3, - 2 ** 2, - Duration.wrap(3 hours), - Duration.wrap(3.5 days), - _vm, - _weth, - anchorStateRegistry, - 10, - PROPOSER, - CHALLENGER + IPermissionedDisputeGame.PDGConstructorParams({ + _gameType: GAME_TYPE, + _absolutePrestate: absolutePrestate, + _maxGameDepth: 2 ** 3, + _splitDepth: 2 ** 2, + _clockExtension: Duration.wrap(3 hours), + _maxClockDuration: Duration.wrap(3.5 days), + _vm: _vm, + _weth: _weth, + _anchorStateRegistry: anchorStateRegistry, + _l2ChainId: 10, + _proposer: PROPOSER, + _challenger: CHALLENGER + }) ) ) ) diff --git a/packages/contracts-bedrock/test/libraries/SafeCall.t.sol b/packages/contracts-bedrock/test/libraries/SafeCall.t.sol index ffdf07b09b83..2317a289428c 100644 --- a/packages/contracts-bedrock/test/libraries/SafeCall.t.sol +++ b/packages/contracts-bedrock/test/libraries/SafeCall.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.15; // Testing utilities import { Test } from "forge-std/Test.sol"; +import { VmSafe } from "forge-std/Vm.sol"; import { StdCheatsSafe } from "forge-std/StdCheats.sol"; // Target contract @@ -122,9 +123,29 @@ contract SafeCall_Test is Test { for (uint64 i = 40_000; i < 100_000; i++) { uint256 snapshot = vm.snapshot(); - // 65_922 is the exact amount of gas required to make the safe call - // successfully. - if (i < 65_922) { + // The values below are best gotten by setting the value to a high number and running the test with a + // verbosity of `-vvv` then setting the value to the value (gas arg) of the failed assertion. + // A faster way to do this for forge coverage cases, is to comment out the optimizer and optimizer runs in + // the foundry.toml file and then run forge test. This is faster because forge test only compiles modified + // contracts unlike forge coverage. + uint256 expected; + + // Because forge coverage always runs with the optimizer disabled, + // if forge coverage is run before testing this with forge test or forge snapshot, forge clean should be + // run first so that it recompiles the contracts using the foundry.toml optimizer settings. + if (vm.isContext(VmSafe.ForgeContext.Coverage)) { + // 66_290 is the exact amount of gas required to make the safe call + // successfully with the optimizer disabled (ran via forge coverage) + expected = 66_290; + } else if (vm.isContext(VmSafe.ForgeContext.Test) || vm.isContext(VmSafe.ForgeContext.Snapshot)) { + // 65_922 is the exact amount of gas required to make the safe call + // successfully with the foundry.toml optimizer settings. + expected = 65_922; + } else { + revert("SafeCall_Test: unknown context"); + } + + if (i < expected) { assertFalse(caller.makeSafeCall(i, 25_000)); } else { vm.expectCallMinGas(address(caller), 0, 25_000, abi.encodeCall(caller.setA, (1))); @@ -142,9 +163,29 @@ contract SafeCall_Test is Test { for (uint64 i = 15_200_000; i < 15_300_000; i++) { uint256 snapshot = vm.snapshot(); - // 15_278_621 is the exact amount of gas required to make the safe call - // successfully. - if (i < 15_278_621) { + // The values below are best gotten by setting the value to a high number and running the test with a + // verbosity of `-vvv` then setting the value to the value (gas arg) of the failed assertion. + // A faster way to do this for forge coverage cases, is to comment out the optimizer and optimizer runs in + // the foundry.toml file and then run forge test. This is faster because forge test only compiles modified + // contracts unlike forge coverage. + uint256 expected; + + // Because forge coverage always runs with the optimizer disabled, + // if forge coverage is run before testing this with forge test or forge snapshot, forge clean should be + // run first so that it recompiles the contracts using the foundry.toml optimizer settings. + if (vm.isContext(VmSafe.ForgeContext.Coverage)) { + // 15_278_645 is the exact amount of gas required to make the safe call + // successfully with the optimizer disabled (ran via forge coverage) + expected = 15_278_989; + } else if (vm.isContext(VmSafe.ForgeContext.Test) || vm.isContext(VmSafe.ForgeContext.Snapshot)) { + // 15_278_621 is the exact amount of gas required to make the safe call + // successfully with the foundry.toml optimizer settings. + expected = 15_278_621; + } else { + revert("SafeCall_Test: unknown context"); + } + + if (i < expected) { assertFalse(caller.makeSafeCall(i, 15_000_000)); } else { vm.expectCallMinGas(address(caller), 0, 15_000_000, abi.encodeCall(caller.setA, (1)));