From 34046982191c21a5e72ed9c825347262c513942c Mon Sep 17 00:00:00 2001 From: AgusDuha <81362284+agusduha@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:46:19 -0300 Subject: [PATCH 01/61] feat: add sender to ERC7802 events (#132) (#13020) --- .../snapshots/abi/OptimismSuperchainERC20.json | 12 ++++++++++++ .../snapshots/abi/SuperchainWETH.json | 12 ++++++++++++ .../contracts-bedrock/snapshots/semver-lock.json | 10 +++++----- .../src/L2/OptimismSuperchainERC20.sol | 4 ++-- .../contracts-bedrock/src/L2/SuperchainERC20.sol | 8 ++++---- packages/contracts-bedrock/src/L2/SuperchainWETH.sol | 8 ++++---- .../contracts-bedrock/src/L2/interfaces/IERC7802.sol | 6 ++++-- .../contracts-bedrock/test/L2/SuperchainERC20.t.sol | 4 ++-- .../contracts-bedrock/test/L2/SuperchainWETH.t.sol | 12 ++++++------ 9 files changed, 51 insertions(+), 25 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20.json b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20.json index 24ac8a88fab..fbe697b864d 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20.json @@ -454,6 +454,12 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" } ], "name": "CrosschainBurn", @@ -473,6 +479,12 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" } ], "name": "CrosschainMint", diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json index 32d84df7d88..a8b4365d742 100644 --- a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json @@ -306,6 +306,12 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" } ], "name": "CrosschainBurn", @@ -325,6 +331,12 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" } ], "name": "CrosschainMint", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index d069a275393..c24e3f8cb6f 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -104,8 +104,8 @@ "sourceCodeHash": "0xa76133db7f449ae742f9ba988ad86ccb5672475f61298b9fefe411b63b63e9f6" }, "src/L2/OptimismSuperchainERC20.sol": { - "initCodeHash": "0x5bc5824030ecdb531e1f615d207cb73cdaa702e198769445d0ddbe717271eba9", - "sourceCodeHash": "0x0819c9411a155dca592d19b60c4176954202e4fe5d632a4ffbf88d465461252c" + "initCodeHash": "0x22fed5371ad9b4c2711ce5cbee889d332887aa5f5ff6b37e36c31acefe3bbeee", + "sourceCodeHash": "0xf68baaee0a09ea51d5a4e821df79976c0914369ebc8e5fd27bbbf89072254fc8" }, "src/L2/OptimismSuperchainERC20Beacon.sol": { "initCodeHash": "0x23dba3ceb9e58646695c306996c9e15251ac79acc6339c1a93d10a4c79da6dab", @@ -121,15 +121,15 @@ }, "src/L2/SuperchainERC20.sol": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "sourceCodeHash": "0xcf39c16893cace1e7d61350bfff05a27f3ce8da8eb0ac02cb5ac7bf603f163fa" + "sourceCodeHash": "0x77adb9ea7a9e9cf3dc5943607dcacacf7a703bd110d2a5627e7075b766aae29f" }, "src/L2/SuperchainTokenBridge.sol": { "initCodeHash": "0x1cd2afdae6dd1b6ebc17f1d529e7d74c9b8b21b02db8589b8e389e2d5523d775", "sourceCodeHash": "0x617aa994f659c5d8ebd54128d994f86f5b175ceca095b024b8524a7898e8ae62" }, "src/L2/SuperchainWETH.sol": { - "initCodeHash": "0x5aef986a7c9c102b1e9b3068e2a2b66adce0a71dd5f39e03694622bf494f8d97", - "sourceCodeHash": "0xa62101a23b860e97f393027c898082a1c73d50679eceb6c6793844af29702359" + "initCodeHash": "0x90aad5698e09994909331dd9665d99a8d5a53e45ba792bf47e4c2efbd48f7699", + "sourceCodeHash": "0x35f0ffcfa027f736b496f3fd2640c043648a49ce325083486ce27f63bfec6d08" }, "src/L2/WETH.sol": { "initCodeHash": "0x17ea1b1c5d5a622d51c2961fde886a5498de63584e654ed1d69ee80dddbe0b17", diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index c323d8b7577..86f73f1d6f9 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -58,8 +58,8 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable { } /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.9 - string public constant override version = "1.0.0-beta.9"; + /// @custom:semver 1.0.0-beta.10 + string public constant override version = "1.0.0-beta.10"; /// @notice Constructs the OptimismSuperchainERC20 contract. constructor() { diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol index b9e6bbfbf78..6d40ff94376 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -13,9 +13,9 @@ import { Unauthorized } from "src/libraries/errors/CommonErrors.sol"; /// the Superchain. Allows the SuperchainTokenBridge to mint and burn tokens as needed. abstract contract SuperchainERC20 is ERC20, IERC7802, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.5 + /// @custom:semver 1.0.0-beta.6 function version() external view virtual returns (string memory) { - return "1.0.0-beta.5"; + return "1.0.0-beta.6"; } /// @notice Allows the SuperchainTokenBridge to mint tokens. @@ -26,7 +26,7 @@ abstract contract SuperchainERC20 is ERC20, IERC7802, ISemver { _mint(_to, _amount); - emit CrosschainMint(_to, _amount); + emit CrosschainMint(_to, _amount, msg.sender); } /// @notice Allows the SuperchainTokenBridge to burn tokens. @@ -37,7 +37,7 @@ abstract contract SuperchainERC20 is ERC20, IERC7802, ISemver { _burn(_from, _amount); - emit CrosschainBurn(_from, _amount); + emit CrosschainBurn(_from, _amount, msg.sender); } /// @inheritdoc IERC165 diff --git a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol index 29e179eba82..d5c37d9cc76 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol @@ -24,8 +24,8 @@ import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErro /// do not use a custom gas token. contract SuperchainWETH is WETH98, IERC7802, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.10 - string public constant version = "1.0.0-beta.10"; + /// @custom:semver 1.0.0-beta.11 + string public constant version = "1.0.0-beta.11"; /// @inheritdoc WETH98 function deposit() public payable override { @@ -74,7 +74,7 @@ contract SuperchainWETH is WETH98, IERC7802, ISemver { IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(_amount); } - emit CrosschainMint(_to, _amount); + emit CrosschainMint(_to, _amount, msg.sender); } /// @notice Allows the SuperchainTokenBridge to burn tokens. @@ -90,7 +90,7 @@ contract SuperchainWETH is WETH98, IERC7802, ISemver { IETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: _amount }(); } - emit CrosschainBurn(_from, _amount); + emit CrosschainBurn(_from, _amount, msg.sender); } /// @inheritdoc IERC165 diff --git a/packages/contracts-bedrock/src/L2/interfaces/IERC7802.sol b/packages/contracts-bedrock/src/L2/interfaces/IERC7802.sol index 469230e822d..38c92d01d8d 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IERC7802.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IERC7802.sol @@ -9,12 +9,14 @@ interface IERC7802 is IERC165 { /// @notice Emitted when a crosschain transfer mints tokens. /// @param to Address of the account tokens are being minted for. /// @param amount Amount of tokens minted. - event CrosschainMint(address indexed to, uint256 amount); + /// @param sender Address of the account that finilized the crosschain transfer. + event CrosschainMint(address indexed to, uint256 amount, address indexed sender); /// @notice Emitted when a crosschain transfer burns tokens. /// @param from Address of the account tokens are being burned from. /// @param amount Amount of tokens burned. - event CrosschainBurn(address indexed from, uint256 amount); + /// @param sender Address of the account that initiated the crosschain transfer. + event CrosschainBurn(address indexed from, uint256 amount, address indexed sender); /// @notice Mint tokens through a crosschain transfer. /// @param _to Address to mint tokens to. diff --git a/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol b/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol index 87f723a9345..2afb4ba03d1 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol @@ -62,7 +62,7 @@ contract SuperchainERC20Test is Test { // Look for the emit of the `CrosschainMint` event vm.expectEmit(address(superchainERC20)); - emit IERC7802.CrosschainMint(_to, _amount); + emit IERC7802.CrosschainMint(_to, _amount, SUPERCHAIN_TOKEN_BRIDGE); // Call the `mint` function with the bridge caller vm.prank(SUPERCHAIN_TOKEN_BRIDGE); @@ -105,7 +105,7 @@ contract SuperchainERC20Test is Test { // Look for the emit of the `CrosschainBurn` event vm.expectEmit(address(superchainERC20)); - emit IERC7802.CrosschainBurn(_from, _amount); + emit IERC7802.CrosschainBurn(_from, _amount, SUPERCHAIN_TOKEN_BRIDGE); // Call the `burn` function with the bridge caller vm.prank(SUPERCHAIN_TOKEN_BRIDGE); diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol index e342a53b602..88ff2ada895 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -28,10 +28,10 @@ contract SuperchainWETH_Test is CommonTest { event Withdrawal(address indexed src, uint256 wad); /// @notice Emitted when a crosschain transfer mints tokens. - event CrosschainMint(address indexed to, uint256 amount); + event CrosschainMint(address indexed to, uint256 amount, address indexed sender); /// @notice Emitted when a crosschain transfer burns tokens. - event CrosschainBurn(address indexed from, uint256 amount); + event CrosschainBurn(address indexed from, uint256 amount, address indexed sender); address internal constant ZERO_ADDRESS = address(0); @@ -162,7 +162,7 @@ contract SuperchainWETH_Test is CommonTest { // Look for the emit of the `CrosschainMint` event vm.expectEmit(address(superchainWeth)); - emit CrosschainMint(_to, _amount); + emit CrosschainMint(_to, _amount, Predeploys.SUPERCHAIN_TOKEN_BRIDGE); // Mock the `isCustomGasToken` function to return false _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(false)); @@ -195,7 +195,7 @@ contract SuperchainWETH_Test is CommonTest { // Look for the emit of the `CrosschainMint` event vm.expectEmit(address(superchainWeth)); - emit CrosschainMint(_to, _amount); + emit CrosschainMint(_to, _amount, Predeploys.SUPERCHAIN_TOKEN_BRIDGE); // Mock the `isCustomGasToken` function to return false _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); @@ -248,7 +248,7 @@ contract SuperchainWETH_Test is CommonTest { // Look for the emit of the `CrosschainBurn` event vm.expectEmit(address(superchainWeth)); - emit CrosschainBurn(_from, _amount); + emit CrosschainBurn(_from, _amount, Predeploys.SUPERCHAIN_TOKEN_BRIDGE); // Mock the `isCustomGasToken` function to return false _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(false)); @@ -290,7 +290,7 @@ contract SuperchainWETH_Test is CommonTest { // Look for the emit of the `CrosschainBurn` event vm.expectEmit(address(superchainWeth)); - emit CrosschainBurn(_from, _amount); + emit CrosschainBurn(_from, _amount, Predeploys.SUPERCHAIN_TOKEN_BRIDGE); // Expect to not call the `burn` function in the `ETHLiquidity` contract vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.burn, ()), 0); From ccb544d0b1dca4eaa7695d636e70f4f20d448842 Mon Sep 17 00:00:00 2001 From: AgusDuha <81362284+agusduha@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:31:58 -0300 Subject: [PATCH 02/61] feat: add dependency set check to L2ToL2CDM (#134) (#13019) --- .../abi/L2ToL2CrossDomainMessenger.json | 5 +++ .../snapshots/semver-lock.json | 4 +- .../src/L2/L2ToL2CrossDomainMessenger.sol | 9 ++++- .../IL2ToL2CrossDomainMessenger.sol | 3 ++ .../test/L2/L2ToL2CrossDomainMessenger.t.sol | 39 ++++++++++++++++++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/abi/L2ToL2CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/abi/L2ToL2CrossDomainMessenger.json index 6434233930d..9f51cc1c3a2 100644 --- a/packages/contracts-bedrock/snapshots/abi/L2ToL2CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/abi/L2ToL2CrossDomainMessenger.json @@ -247,6 +247,11 @@ "name": "IdOriginNotL2ToL2CrossDomainMessenger", "type": "error" }, + { + "inputs": [], + "name": "InvalidChainId", + "type": "error" + }, { "inputs": [], "name": "MessageAlreadyRelayed", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index c24e3f8cb6f..444f4522c65 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -100,8 +100,8 @@ "sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c" }, "src/L2/L2ToL2CrossDomainMessenger.sol": { - "initCodeHash": "0x2a1a1ee4f47175ce661ee8e4e50cfa879b082dcb5278b1d66ddda00ed77bb744", - "sourceCodeHash": "0xa76133db7f449ae742f9ba988ad86ccb5672475f61298b9fefe411b63b63e9f6" + "initCodeHash": "0xc1c80c662aafebb639f62f17d9fefd6954947fd43dc31c278950727491471a94", + "sourceCodeHash": "0xac12ab96ffe91c75bfe74768271a725e1cbe3996b16284171440dd71bcc215b6" }, "src/L2/OptimismSuperchainERC20.sol": { "initCodeHash": "0x22fed5371ad9b4c2711ce5cbee889d332887aa5f5ff6b37e36c31acefe3bbeee", diff --git a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol index 6b1d7327dbc..bf53133484d 100644 --- a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol @@ -8,6 +8,7 @@ import { CrossL2Inbox, Identifier } from "src/L2/CrossL2Inbox.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; import { TransientReentrancyAware } from "src/libraries/TransientContext.sol"; +import { IDependencySet } from "src/L2/interfaces/IDependencySet.sol"; /// @notice Thrown when a non-written slot in transient storage is attempted to be read from. error NotEntered(); @@ -39,6 +40,9 @@ error ReentrantCall(); /// @notice Thrown when a call to the target contract during message relay fails. error TargetCallFailed(); +/// @notice Thrown when attempting to use a chain ID that is not in the dependency set. +error InvalidChainId(); + /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000023 /// @title L2ToL2CrossDomainMessenger @@ -65,8 +69,8 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { uint16 public constant messageVersion = uint16(0); /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.10 - string public constant version = "1.0.0-beta.10"; + /// @custom:semver 1.0.0-beta.11 + string public constant version = "1.0.0-beta.11"; /// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this /// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again. @@ -130,6 +134,7 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { if (_destination == block.chainid) revert MessageDestinationSameChain(); if (_target == Predeploys.CROSS_L2_INBOX) revert MessageTargetCrossL2Inbox(); if (_target == Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert MessageTargetL2ToL2CrossDomainMessenger(); + if (!IDependencySet(Predeploys.L1_BLOCK_ATTRIBUTES).isInDependencySet(_destination)) revert InvalidChainId(); uint256 nonce = messageNonce(); emit SentMessage(_destination, _target, nonce, msg.sender, _message); diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol index 00ca4906b5c..89311cf18f0 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol @@ -42,6 +42,9 @@ interface IL2ToL2CrossDomainMessenger { /// @notice Thrown when a call to the target contract during message relay fails. error TargetCallFailed(); + /// @notice Thrown when attempting to use a chain ID that is not in the dependency set. + error InvalidChainId(); + /// @notice Emitted whenever a message is sent to a destination /// @param destination Chain ID of the destination chain. /// @param target Target contract or wallet address. diff --git a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol index 1e5e04edc25..0775eb588d2 100644 --- a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol @@ -22,7 +22,9 @@ import { MessageTargetL2ToL2CrossDomainMessenger, MessageAlreadyRelayed, ReentrantCall, - TargetCallFailed + TargetCallFailed, + IDependencySet, + InvalidChainId } from "src/L2/L2ToL2CrossDomainMessenger.sol"; /// @title L2ToL2CrossDomainMessengerWithModifiableTransientStorage @@ -85,6 +87,13 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + // Mock the call over the `isInDependencySet` function to return true + vm.mockCall( + Predeploys.L1_BLOCK_ATTRIBUTES, + abi.encodeCall(IDependencySet.isInDependencySet, (_destination)), + abi.encode(true) + ); + // Get the current message nonce uint256 messageNonce = l2ToL2CrossDomainMessenger.messageNonce(); @@ -193,6 +202,34 @@ contract L2ToL2CrossDomainMessengerTest is Test { }); } + /// @notice Tests the `sendMessage` function reverts when the `destination` is not in the dependency set. + function testFuzz_sendMessage_notInDependencySet_reverts( + uint256 _destination, + address _target, + bytes calldata _message + ) + external + { + // Ensure the destination is not the same as the source, otherwise the function will revert + vm.assume(_destination != block.chainid); + + // Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger + vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + // Mock the call over the `isInDependencySet` function to return false + vm.mockCall( + Predeploys.L1_BLOCK_ATTRIBUTES, + abi.encodeCall(IDependencySet.isInDependencySet, (_destination)), + abi.encode(false) + ); + + // Expect a revert with the InvalidChainId selector + vm.expectRevert(InvalidChainId.selector); + + // Call `sendMessage` with a destination that is not in the dependency set to provoke revert + l2ToL2CrossDomainMessenger.sendMessage(_destination, _target, _message); + } + /// @dev Tests that the `relayMessage` function succeeds and emits the correct RelayedMessage event. function testFuzz_relayMessage_succeeds( uint256 _source, From 8f5c20ee7724e69dc76634ff88377ace16ea2eb0 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Thu, 21 Nov 2024 23:27:53 +0100 Subject: [PATCH 03/61] improve Legacy Contract tests (#13022) * improve DeployerWhitelist test * fix L1BlockNumber fallback test * fixes --- .../test/legacy/DeployerWhitelist.t.sol | 99 ++++++++++++++++++- .../test/legacy/L1BlockNumber.t.sol | 2 +- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol index 3f140e9a072..76a0e6aa084 100644 --- a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol +++ b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol @@ -10,6 +10,11 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; contract DeployerWhitelist_Test is Test { IDeployerWhitelist list; + address owner = address(12345); + + event OwnerChanged(address oldOwner, address newOwner); + event WhitelistDisabled(address oldOwner); + event WhitelistStatusChanged(address deployer, bool whitelisted); /// @dev Sets up the test suite. function setUp() public { @@ -27,10 +32,96 @@ contract DeployerWhitelist_Test is Test { } /// @dev Tests that `setOwner` correctly sets the contract owner. - function test_storageSlots_succeeds() external { - vm.prank(list.owner()); - list.setOwner(address(1)); + function test_setOwner_succeeds(address _owner) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + _owner = address(uint160(bound(uint160(_owner), 1, type(uint160).max))); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit OwnerChanged(owner, _owner); + list.setOwner(_owner); + + assertEq(list.owner(), _owner); + } + + /// @dev Tests that `setOwner` reverts when the caller is not the owner. + function test_setOwner_reverts(address _caller, address _owner) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); + + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.setOwner(_owner); + } + + /// @dev Tests that `setOwner` reverts when the new owner is the zero address. + function test_setOwner_reverts_zeroAddress() external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectRevert(bytes("DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment")); + list.setOwner(address(0)); + } + + /// @dev Tests that `enableArbitraryContractDeployment` correctly disables the whitelist. + function test_enableArbitraryContractDeployment_succeeds() external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit WhitelistDisabled(owner); + list.enableArbitraryContractDeployment(); + + assertEq(list.owner(), address(0)); + + // Any address is allowed to deploy contracts even if they are not whitelisted + assertEq(list.whitelist(address(1)), false); + assertEq(list.isDeployerAllowed(address(1)), true); + } + + /// @dev Tests that `enableArbitraryContractDeployment` reverts when the caller is not the owner. + function test_enableArbitraryContractDeployment_reverts(address _caller) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); + + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.enableArbitraryContractDeployment(); + } + + /// @dev Tests that `setWhitelistedDeployer` correctly sets the whitelist status of a deployer. + function test_setWhitelistedDeployer_succeeds(address _deployer, bool _isWhitelisted) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit WhitelistStatusChanged(_deployer, _isWhitelisted); + list.setWhitelistedDeployer(_deployer, _isWhitelisted); + + assertEq(list.whitelist(_deployer), _isWhitelisted); + + // _deployer is whitelisted or not (and arbitrary contract deployment is not enabled) + assertNotEq(list.owner(), address(0)); + assertEq(list.isDeployerAllowed(_deployer), _isWhitelisted); + } + + /// @dev Tests that `setWhitelistedDeployer` reverts when the caller is not the owner. + function test_setWhitelistedDeployer_reverts(address _caller, address _deployer, bool _isWhitelisted) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); - assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0)))); + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.setWhitelistedDeployer(_deployer, _isWhitelisted); } } diff --git a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol index 49758739d2d..aa8d2545106 100644 --- a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol @@ -49,7 +49,7 @@ contract L1BlockNumberTest is Test { /// @dev Tests that `fallback` is correctly dispatched. function test_fallback_succeeds() external { - (bool success, bytes memory ret) = address(bn).call(hex""); + (bool success, bytes memory ret) = address(bn).call(hex"11"); assertEq(success, true); assertEq(ret, abi.encode(number)); } From e52030dba4d6130874f80e80900961c342c8c074 Mon Sep 17 00:00:00 2001 From: clabby Date: Thu, 21 Nov 2024 19:22:51 -0500 Subject: [PATCH 04/61] chore(op-challenger): Update kona native mode flag (#13023) --- .../game/fault/trace/vm/kona_server_executor.go | 9 ++++----- op-e2e/actions/proofs/helpers/kona.go | 7 +++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/op-challenger/game/fault/trace/vm/kona_server_executor.go b/op-challenger/game/fault/trace/vm/kona_server_executor.go index baaa253088f..ffb74d9a31b 100644 --- a/op-challenger/game/fault/trace/vm/kona_server_executor.go +++ b/op-challenger/game/fault/trace/vm/kona_server_executor.go @@ -9,8 +9,7 @@ import ( ) type KonaExecutor struct { - nativeMode bool - clientBinPath string + nativeMode bool } var _ OracleServerExecutor = (*KonaExecutor)(nil) @@ -19,8 +18,8 @@ func NewKonaExecutor() *KonaExecutor { return &KonaExecutor{nativeMode: false} } -func NewNativeKonaExecutor(clientBinPath string) *KonaExecutor { - return &KonaExecutor{nativeMode: true, clientBinPath: clientBinPath} +func NewNativeKonaExecutor() *KonaExecutor { + return &KonaExecutor{nativeMode: true} } func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { @@ -37,7 +36,7 @@ func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.Lo } if s.nativeMode { - args = append(args, "--exec", s.clientBinPath) + args = append(args, "--native") } else { args = append(args, "--server") args = append(args, "--data-dir", dataDir) diff --git a/op-e2e/actions/proofs/helpers/kona.go b/op-e2e/actions/proofs/helpers/kona.go index 9d34a98dda0..dc9b98cd809 100644 --- a/op-e2e/actions/proofs/helpers/kona.go +++ b/op-e2e/actions/proofs/helpers/kona.go @@ -16,15 +16,14 @@ import ( "github.com/stretchr/testify/require" ) -var konaHostPath, konaClientPath string +var konaHostPath string func init() { konaHostPath = os.Getenv("KONA_HOST_PATH") - konaClientPath = os.Getenv("KONA_CLIENT_PATH") } func IsKonaConfigured() bool { - return konaHostPath != "" && konaClientPath != "" + return konaHostPath != "" } func RunKonaNative( @@ -57,7 +56,7 @@ func RunKonaNative( L2Claim: fixtureInputs.L2Claim, L2BlockNumber: big.NewInt(int64(fixtureInputs.L2BlockNumber)), } - hostCmd, err := vm.NewNativeKonaExecutor(konaClientPath).OracleCommand(vmCfg, workDir, inputs) + hostCmd, err := vm.NewNativeKonaExecutor().OracleCommand(vmCfg, workDir, inputs) require.NoError(t, err) cmd := exec.Command(hostCmd[0], hostCmd[1:]...) From 5aa14b374ec906d32a824b4c7acbcb06366a88d0 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Fri, 22 Nov 2024 12:42:39 +0800 Subject: [PATCH 05/61] op-batcher: fix a deadlock (#13014) * fix a deadlock * add comment --- op-batcher/batcher/driver.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index dde08ac8419..08cf867aed4 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -557,8 +557,11 @@ func (l *BatchSubmitter) throttlingLoop(ctx context.Context) { // We'd probably hit this error right after startup, so a short shutdown duration should suffice. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - // Always returns nil. An error is only returned to expose this function as an RPC. - _ = l.StopBatchSubmitting(ctx) + // Call StopBatchSubmitting in another goroutine to avoid deadlock. + go func() { + // Always returns nil. An error is only returned to expose this function as an RPC. + _ = l.StopBatchSubmitting(ctx) + }() return } else if err != nil { l.Log.Error("SetMaxDASize rpc failed, retrying.", "err", err) From 99810e0b39a44ca2a801adf732acb2d7557b32d6 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 22 Nov 2024 09:46:35 -0700 Subject: [PATCH 06/61] Revert "improve Legacy Contract tests (#13022)" (#13031) This reverts commit 8f5c20ee7724e69dc76634ff88377ace16ea2eb0. --- .../test/legacy/DeployerWhitelist.t.sol | 99 +------------------ .../test/legacy/L1BlockNumber.t.sol | 2 +- 2 files changed, 5 insertions(+), 96 deletions(-) diff --git a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol index 76a0e6aa084..3f140e9a072 100644 --- a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol +++ b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol @@ -10,11 +10,6 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; contract DeployerWhitelist_Test is Test { IDeployerWhitelist list; - address owner = address(12345); - - event OwnerChanged(address oldOwner, address newOwner); - event WhitelistDisabled(address oldOwner); - event WhitelistStatusChanged(address deployer, bool whitelisted); /// @dev Sets up the test suite. function setUp() public { @@ -32,96 +27,10 @@ contract DeployerWhitelist_Test is Test { } /// @dev Tests that `setOwner` correctly sets the contract owner. - function test_setOwner_succeeds(address _owner) external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - _owner = address(uint160(bound(uint160(_owner), 1, type(uint160).max))); - - vm.prank(owner); - vm.expectEmit(true, true, true, true); - emit OwnerChanged(owner, _owner); - list.setOwner(_owner); - - assertEq(list.owner(), _owner); - } - - /// @dev Tests that `setOwner` reverts when the caller is not the owner. - function test_setOwner_reverts(address _caller, address _owner) external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.assume(_caller != owner); - - vm.prank(_caller); - vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); - list.setOwner(_owner); - } - - /// @dev Tests that `setOwner` reverts when the new owner is the zero address. - function test_setOwner_reverts_zeroAddress() external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.prank(owner); - vm.expectRevert(bytes("DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment")); - list.setOwner(address(0)); - } - - /// @dev Tests that `enableArbitraryContractDeployment` correctly disables the whitelist. - function test_enableArbitraryContractDeployment_succeeds() external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.prank(owner); - vm.expectEmit(true, true, true, true); - emit WhitelistDisabled(owner); - list.enableArbitraryContractDeployment(); - - assertEq(list.owner(), address(0)); - - // Any address is allowed to deploy contracts even if they are not whitelisted - assertEq(list.whitelist(address(1)), false); - assertEq(list.isDeployerAllowed(address(1)), true); - } - - /// @dev Tests that `enableArbitraryContractDeployment` reverts when the caller is not the owner. - function test_enableArbitraryContractDeployment_reverts(address _caller) external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.assume(_caller != owner); - - vm.prank(_caller); - vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); - list.enableArbitraryContractDeployment(); - } - - /// @dev Tests that `setWhitelistedDeployer` correctly sets the whitelist status of a deployer. - function test_setWhitelistedDeployer_succeeds(address _deployer, bool _isWhitelisted) external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.prank(owner); - vm.expectEmit(true, true, true, true); - emit WhitelistStatusChanged(_deployer, _isWhitelisted); - list.setWhitelistedDeployer(_deployer, _isWhitelisted); - - assertEq(list.whitelist(_deployer), _isWhitelisted); - - // _deployer is whitelisted or not (and arbitrary contract deployment is not enabled) - assertNotEq(list.owner(), address(0)); - assertEq(list.isDeployerAllowed(_deployer), _isWhitelisted); - } - - /// @dev Tests that `setWhitelistedDeployer` reverts when the caller is not the owner. - function test_setWhitelistedDeployer_reverts(address _caller, address _deployer, bool _isWhitelisted) external { - vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); - assertEq(list.owner(), owner); - - vm.assume(_caller != owner); + function test_storageSlots_succeeds() external { + vm.prank(list.owner()); + list.setOwner(address(1)); - vm.prank(_caller); - vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); - list.setWhitelistedDeployer(_deployer, _isWhitelisted); + assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0)))); } } diff --git a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol index aa8d2545106..49758739d2d 100644 --- a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol @@ -49,7 +49,7 @@ contract L1BlockNumberTest is Test { /// @dev Tests that `fallback` is correctly dispatched. function test_fallback_succeeds() external { - (bool success, bytes memory ret) = address(bn).call(hex"11"); + (bool success, bytes memory ret) = address(bn).call(hex""); assertEq(success, true); assertEq(ret, abi.encode(number)); } From 1c36df3e43a2ce5f1d61fafdfccb570b31e10abb Mon Sep 17 00:00:00 2001 From: Sam Stokes <35908605+bitwiseguy@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:58:14 -0500 Subject: [PATCH 07/61] op-node: log mgasps across block building/inserting lifecycle (#12907) * op-node: log mgasps across block processing lifecycle * op-node: add 'import_time' field to block processing log * op-node: make log message more descriptive * op-node: log legacy codepath for InsertUnsafePayload * op-node: include final ForkchoiceUpdate in block insertion time * op-node: remove unused BuildTime field from events * op-node: encapsulate log logic in TryUpdateEngineEvent methods * op-node: linter fix * op-node: add comment and adjust sync log wording * op-node: fix BlockHash, BlockNumber in log * op-node: seq add BuildStarted to PayloadProcessEvent * op-node: refactor getBlockProcessingMetrics, protect against divide-by-zero --- op-node/rollup/engine/build_seal.go | 13 ++-- op-node/rollup/engine/build_sealed.go | 14 +++-- op-node/rollup/engine/engine_controller.go | 14 +++++ op-node/rollup/engine/events.go | 61 ++++++++++++++++++- op-node/rollup/engine/payload_process.go | 14 ++++- op-node/rollup/engine/payload_success.go | 18 +++--- op-node/rollup/sequencing/sequencer.go | 9 +-- .../rollup/sequencing/sequencer_chaos_test.go | 8 ++- 8 files changed, 124 insertions(+), 27 deletions(-) diff --git a/op-node/rollup/engine/build_seal.go b/op-node/rollup/engine/build_seal.go index 25c1d95b8e7..cd3ca888827 100644 --- a/op-node/rollup/engine/build_seal.go +++ b/op-node/rollup/engine/build_seal.go @@ -113,14 +113,15 @@ func (eq *EngDeriver) onBuildSeal(ev BuildSealEvent) { depositCount, _ := lastDeposit(envelope.ExecutionPayload.Transactions) eq.metrics.CountSequencedTxsInBlock(txnCount, depositCount) - eq.log.Debug("Processed new L2 block", "l2_unsafe", ref, "l1_origin", ref.L1Origin, + eq.log.Debug("Built new L2 block", "l2_unsafe", ref, "l1_origin", ref.L1Origin, "txs", txnCount, "deposits", depositCount, "time", ref.Time, "seal_time", sealTime, "build_time", buildTime) eq.emitter.Emit(BuildSealedEvent{ - Concluding: ev.Concluding, - DerivedFrom: ev.DerivedFrom, - Info: ev.Info, - Envelope: envelope, - Ref: ref, + Concluding: ev.Concluding, + DerivedFrom: ev.DerivedFrom, + BuildStarted: ev.BuildStarted, + Info: ev.Info, + Envelope: envelope, + Ref: ref, }) } diff --git a/op-node/rollup/engine/build_sealed.go b/op-node/rollup/engine/build_sealed.go index eb2680850a7..5ceff489ecc 100644 --- a/op-node/rollup/engine/build_sealed.go +++ b/op-node/rollup/engine/build_sealed.go @@ -1,6 +1,8 @@ package engine import ( + "time" + "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -10,7 +12,8 @@ type BuildSealedEvent struct { // if payload should be promoted to (local) safe (must also be pending safe, see DerivedFrom) Concluding bool // payload is promoted to pending-safe if non-zero - DerivedFrom eth.L1BlockRef + DerivedFrom eth.L1BlockRef + BuildStarted time.Time Info eth.PayloadInfo Envelope *eth.ExecutionPayloadEnvelope @@ -25,10 +28,11 @@ func (eq *EngDeriver) onBuildSealed(ev BuildSealedEvent) { // If a (pending) safe block, immediately process the block if ev.DerivedFrom != (eth.L1BlockRef{}) { eq.emitter.Emit(PayloadProcessEvent{ - Concluding: ev.Concluding, - DerivedFrom: ev.DerivedFrom, - Envelope: ev.Envelope, - Ref: ev.Ref, + Concluding: ev.Concluding, + DerivedFrom: ev.DerivedFrom, + Envelope: ev.Envelope, + Ref: ev.Ref, + BuildStarted: ev.BuildStarted, }) } } diff --git a/op-node/rollup/engine/engine_controller.go b/op-node/rollup/engine/engine_controller.go index b088e382f07..907238e84a9 100644 --- a/op-node/rollup/engine/engine_controller.go +++ b/op-node/rollup/engine/engine_controller.go @@ -330,6 +330,7 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et } } // Insert the payload & then call FCU + newPayloadStart := time.Now() status, err := e.engine.NewPayload(ctx, envelope.ExecutionPayload, envelope.ParentBeaconBlockRoot) if err != nil { return derive.NewTemporaryError(fmt.Errorf("failed to update insert payload: %w", err)) @@ -342,6 +343,7 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et return derive.NewTemporaryError(fmt.Errorf("cannot process unsafe payload: new - %v; parent: %v; err: %w", payload.ID(), payload.ParentID(), eth.NewPayloadErr(payload, status))) } + newPayloadFinish := time.Now() // Mark the new payload as valid fc := eth.ForkchoiceState{ @@ -361,6 +363,7 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et } logFn := e.logSyncProgressMaybe() defer logFn() + fcu2Start := time.Now() fcRes, err := e.engine.ForkchoiceUpdate(ctx, &fc, nil) if err != nil { var rpcErr rpc.Error @@ -380,6 +383,7 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et return derive.NewTemporaryError(fmt.Errorf("cannot prepare unsafe chain for new payload: new - %v; parent: %v; err: %w", payload.ID(), payload.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) } + fcu2Finish := time.Now() e.SetUnsafeHead(ref) e.needFCUCall = false e.emitter.Emit(UnsafeUpdateEvent{Ref: ref}) @@ -397,6 +401,16 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et }) } + totalTime := fcu2Finish.Sub(newPayloadStart) + e.log.Info("Inserted new L2 unsafe block (synchronous)", + "hash", envelope.ExecutionPayload.BlockHash, + "number", uint64(envelope.ExecutionPayload.BlockNumber), + "newpayload_time", common.PrettyDuration(newPayloadFinish.Sub(newPayloadStart)), + "fcu2_time", common.PrettyDuration(fcu2Finish.Sub(fcu2Start)), + "total_time", common.PrettyDuration(totalTime), + "mgas", float64(envelope.ExecutionPayload.GasUsed)/1000000, + "mgasps", float64(envelope.ExecutionPayload.GasUsed)*1000/float64(totalTime)) + return nil } diff --git a/op-node/rollup/engine/events.go b/op-node/rollup/engine/events.go index b6ba85cbcbe..fbc8b7b1db2 100644 --- a/op-node/rollup/engine/events.go +++ b/op-node/rollup/engine/events.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -203,12 +204,67 @@ func (ev TryBackupUnsafeReorgEvent) String() string { return "try-backup-unsafe-reorg" } -type TryUpdateEngineEvent struct{} +type TryUpdateEngineEvent struct { + // These fields will be zero-value (BuildStarted,InsertStarted=time.Time{}, Envelope=nil) if + // this event is emitted outside of engineDeriver.onPayloadSuccess + BuildStarted time.Time + InsertStarted time.Time + Envelope *eth.ExecutionPayloadEnvelope +} func (ev TryUpdateEngineEvent) String() string { return "try-update-engine" } +// Checks for the existence of the Envelope field, which is only +// added by the PayloadSuccessEvent +func (ev TryUpdateEngineEvent) triggeredByPayloadSuccess() bool { + return ev.Envelope != nil +} + +// Returns key/value pairs that can be logged and are useful for plotting +// block build/insert time as a way to measure performance. +func (ev TryUpdateEngineEvent) getBlockProcessingMetrics() []interface{} { + fcuFinish := time.Now() + payload := ev.Envelope.ExecutionPayload + + logValues := []interface{}{ + "hash", payload.BlockHash, + "number", uint64(payload.BlockNumber), + "state_root", payload.StateRoot, + "timestamp", uint64(payload.Timestamp), + "parent", payload.ParentHash, + "prev_randao", payload.PrevRandao, + "fee_recipient", payload.FeeRecipient, + "txs", len(payload.Transactions), + } + + var totalTime time.Duration + var mgasps float64 + if !ev.BuildStarted.IsZero() { + totalTime = fcuFinish.Sub(ev.BuildStarted) + logValues = append(logValues, + "build_time", common.PrettyDuration(ev.InsertStarted.Sub(ev.BuildStarted)), + "insert_time", common.PrettyDuration(fcuFinish.Sub(ev.InsertStarted)), + ) + } else if !ev.InsertStarted.IsZero() { + totalTime = fcuFinish.Sub(ev.InsertStarted) + } + + // Avoid divide-by-zero for mgasps + if totalTime > 0 { + mgasps = float64(payload.GasUsed) * 1000 / float64(totalTime) + } + + logValues = append(logValues, + "total_time", common.PrettyDuration(totalTime), + "mgas", float64(payload.GasUsed)/1000000, + "mgasps", mgasps, + ) + + return logValues +} + type ForceEngineResetEvent struct { Unsafe, Safe, Finalized eth.L2BlockRef } @@ -322,6 +378,9 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { } else { d.emitter.Emit(rollup.CriticalErrorEvent{Err: fmt.Errorf("unexpected TryUpdateEngine error type: %w", err)}) } + } else if x.triggeredByPayloadSuccess() { + logValues := x.getBlockProcessingMetrics() + d.log.Info("Inserted new L2 unsafe block", logValues...) } case ProcessUnsafePayloadEvent: ref, err := derive.PayloadToBlockRef(d.cfg, x.Envelope.ExecutionPayload) diff --git a/op-node/rollup/engine/payload_process.go b/op-node/rollup/engine/payload_process.go index 62d7ded47f0..272fce3febc 100644 --- a/op-node/rollup/engine/payload_process.go +++ b/op-node/rollup/engine/payload_process.go @@ -3,6 +3,7 @@ package engine import ( "context" "fmt" + "time" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -12,7 +13,8 @@ type PayloadProcessEvent struct { // if payload should be promoted to (local) safe (must also be pending safe, see DerivedFrom) Concluding bool // payload is promoted to pending-safe if non-zero - DerivedFrom eth.L1BlockRef + DerivedFrom eth.L1BlockRef + BuildStarted time.Time Envelope *eth.ExecutionPayloadEnvelope Ref eth.L2BlockRef @@ -26,6 +28,7 @@ func (eq *EngDeriver) onPayloadProcess(ev PayloadProcessEvent) { ctx, cancel := context.WithTimeout(eq.ctx, payloadProcessTimeout) defer cancel() + insertStart := time.Now() status, err := eq.ec.engine.NewPayload(ctx, ev.Envelope.ExecutionPayload, ev.Envelope.ParentBeaconBlockRoot) if err != nil { @@ -49,7 +52,14 @@ func (eq *EngDeriver) onPayloadProcess(ev PayloadProcessEvent) { }) return case eth.ExecutionValid: - eq.emitter.Emit(PayloadSuccessEvent(ev)) + eq.emitter.Emit(PayloadSuccessEvent{ + Concluding: ev.Concluding, + DerivedFrom: ev.DerivedFrom, + BuildStarted: ev.BuildStarted, + InsertStarted: insertStart, + Envelope: ev.Envelope, + Ref: ev.Ref, + }) return default: eq.emitter.Emit(rollup.EngineTemporaryErrorEvent{ diff --git a/op-node/rollup/engine/payload_success.go b/op-node/rollup/engine/payload_success.go index c00d8e81ea7..17d8b0163b5 100644 --- a/op-node/rollup/engine/payload_success.go +++ b/op-node/rollup/engine/payload_success.go @@ -1,6 +1,8 @@ package engine import ( + "time" + "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -8,7 +10,9 @@ type PayloadSuccessEvent struct { // if payload should be promoted to (local) safe (must also be pending safe, see DerivedFrom) Concluding bool // payload is promoted to pending-safe if non-zero - DerivedFrom eth.L1BlockRef + DerivedFrom eth.L1BlockRef + BuildStarted time.Time + InsertStarted time.Time Envelope *eth.ExecutionPayloadEnvelope Ref eth.L2BlockRef @@ -30,11 +34,9 @@ func (eq *EngDeriver) onPayloadSuccess(ev PayloadSuccessEvent) { }) } - payload := ev.Envelope.ExecutionPayload - eq.log.Info("Inserted block", "hash", payload.BlockHash, "number", uint64(payload.BlockNumber), - "state_root", payload.StateRoot, "timestamp", uint64(payload.Timestamp), "parent", payload.ParentHash, - "prev_randao", payload.PrevRandao, "fee_recipient", payload.FeeRecipient, - "txs", len(payload.Transactions), "concluding", ev.Concluding, "derived_from", ev.DerivedFrom) - - eq.emitter.Emit(TryUpdateEngineEvent{}) + eq.emitter.Emit(TryUpdateEngineEvent{ + BuildStarted: ev.BuildStarted, + InsertStarted: ev.InsertStarted, + Envelope: ev.Envelope, + }) } diff --git a/op-node/rollup/sequencing/sequencer.go b/op-node/rollup/sequencing/sequencer.go index e8b7033273e..2476b9b639f 100644 --- a/op-node/rollup/sequencing/sequencer.go +++ b/op-node/rollup/sequencing/sequencer.go @@ -282,10 +282,11 @@ func (d *Sequencer) onBuildSealed(x engine.BuildSealedEvent) { d.asyncGossip.Gossip(x.Envelope) // Now after having gossiped the block, try to put it in our own canonical chain d.emitter.Emit(engine.PayloadProcessEvent{ - Concluding: x.Concluding, - DerivedFrom: x.DerivedFrom, - Envelope: x.Envelope, - Ref: x.Ref, + Concluding: x.Concluding, + DerivedFrom: x.DerivedFrom, + BuildStarted: x.BuildStarted, + Envelope: x.Envelope, + Ref: x.Ref, }) d.latest.Ref = x.Ref d.latestSealed = x.Ref diff --git a/op-node/rollup/sequencing/sequencer_chaos_test.go b/op-node/rollup/sequencing/sequencer_chaos_test.go index d5000fbed33..93ba254c1b5 100644 --- a/op-node/rollup/sequencing/sequencer_chaos_test.go +++ b/op-node/rollup/sequencing/sequencer_chaos_test.go @@ -216,7 +216,13 @@ func (c *ChaoticEngine) OnEvent(ev event.Event) bool { c.clockRandomIncrement(0, time.Second*3) } c.unsafe = x.Ref - c.emitter.Emit(engine.PayloadSuccessEvent(x)) + c.emitter.Emit(engine.PayloadSuccessEvent{ + Concluding: x.Concluding, + DerivedFrom: x.DerivedFrom, + BuildStarted: x.BuildStarted, + Envelope: x.Envelope, + Ref: x.Ref, + }) // With event delay, the engine would update and signal the new forkchoice. c.emitter.Emit(engine.ForkchoiceRequestEvent{}) } From ae24f01d19355e7511b805afda933b7e918e8cdf Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 22 Nov 2024 10:02:57 -0700 Subject: [PATCH 08/61] op-service: Remove txmgr queue timing test (#13032) The tests in the txmgr queue were asserting that calls complete within a certain time window. This was causing flakes, particularly when the CI runner was under load. Generally we should avoid tests that use fixed durations as a way of asserting that code functions correctly. --- op-service/txmgr/queue_test.go | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/op-service/txmgr/queue_test.go b/op-service/txmgr/queue_test.go index 549142c8592..00219b913ad 100644 --- a/op-service/txmgr/queue_test.go +++ b/op-service/txmgr/queue_test.go @@ -58,12 +58,11 @@ func (b *mockBackendWithNonce) NonceAt(ctx context.Context, account common.Addre func TestQueue_Send(t *testing.T) { testCases := []struct { - name string // name of the test - max uint64 // max concurrency of the queue - calls []queueCall // calls to the queue - txs []testTx // txs to generate from the factory (and potentially error in send) - nonces []uint64 // expected sent tx nonces after all calls are made - total time.Duration // approx. total time it should take to complete all queue calls + name string // name of the test + max uint64 // max concurrency of the queue + calls []queueCall // calls to the queue + txs []testTx // txs to generate from the factory (and potentially error in send) + nonces []uint64 // expected sent tx nonces after all calls are made }{ { name: "success", @@ -77,7 +76,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1}, - total: 1 * time.Second, }, { name: "no limit", @@ -91,7 +89,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1}, - total: 1 * time.Second, }, { name: "single threaded", @@ -105,7 +102,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0}, - total: 1 * time.Second, }, { name: "single threaded blocking", @@ -122,7 +118,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1, 2}, - total: 3 * time.Second, }, { name: "dual threaded blocking", @@ -143,7 +138,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1, 2, 3, 4}, - total: 3 * time.Second, }, { name: "subsequent txs fail after tx failure", @@ -159,7 +153,6 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1}, - total: 1 * time.Second, }, } for _, test := range testCases { @@ -209,7 +202,6 @@ func TestQueue_Send(t *testing.T) { queue := NewQueue[int](ctx, mgr, test.max) // make all the queue calls given in the test case - start := time.Now() receiptChs := make([]chan TxReceipt[int], len(test.calls)) for i, c := range test.calls { msg := fmt.Sprintf("Call %d", i) @@ -223,10 +215,6 @@ func TestQueue_Send(t *testing.T) { } // wait for the queue to drain (all txs complete or failed) _ = queue.Wait() - duration := time.Since(start) - // expect the execution time within a certain window - now := time.Now() - require.WithinDuration(t, now.Add(test.total), now.Add(duration), 500*time.Millisecond, "unexpected queue transaction timing") // check that the nonces match slices.Sort(nonces) require.Equal(t, test.nonces, nonces, "expected nonces do not match") From f9a38de214fd272bb193680f94b09803e50b17b5 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Sat, 23 Nov 2024 01:26:22 +0800 Subject: [PATCH 09/61] show more info for ErrInvalidChannelTimeout (#13008) --- op-batcher/batcher/channel_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-batcher/batcher/channel_config.go b/op-batcher/batcher/channel_config.go index 45dc1d4dcfa..e62ea26eee4 100644 --- a/op-batcher/batcher/channel_config.go +++ b/op-batcher/batcher/channel_config.go @@ -104,7 +104,7 @@ func (cc *ChannelConfig) Check() error { // The [ChannelTimeout] must be larger than the [SubSafetyMargin]. // Otherwise, new blocks would always be considered timed out. if cc.ChannelTimeout < cc.SubSafetyMargin { - return ErrInvalidChannelTimeout + return fmt.Errorf("%w: %d < %d", ErrInvalidChannelTimeout, cc.ChannelTimeout, cc.SubSafetyMargin) } // The max frame size must at least be able to accommodate the constant From d139cc98322022e7b6aed7cea5e5d3ec4b5f2d82 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 22 Nov 2024 12:30:32 -0500 Subject: [PATCH 10/61] fix(ci): contracts test names check failures (#13034) lint-forge-tests-check-no-build was causing issues in CI because it was running as part of contracts-bedrock-checks which depends on contracts-bedrock-build. contracts-bedrock-build builds the contract files EXCEPT for tests whenever contracts-bedrock has changed. This means that contracts-bedrock-build would not build any test files and therefore lint-forge-tests-check-no-build would not find any test files to check and the job would do nothing. However, when contracts-bedrock is NOT changed, the build job gets the full set of artifacts INCLUDING test artifacts from the cache. This would trigger the full check to actually be run and it would properly fail. This PR moves that particular check into contracts-bedrock-tests so that it's guaranteed to have all of the compiled contracts. --- .circleci/config.yml | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 089b13c337f..797e7f20655 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -684,6 +684,10 @@ jobs: name: Build go-ffi command: just build-go-ffi working_directory: packages/contracts-bedrock + - run: + name: Lint forge test names + command: just lint-forge-tests-check-no-build + working_directory: packages/contracts-bedrock - run: name: Run tests command: | @@ -750,22 +754,7 @@ jobs: - run-contracts-check: command: unused-imports-check-no-build - run-contracts-check: - command: lint-forge-tests-check-no-build - - contracts-bedrock-validate-spacers: - docker: - - image: <> - resource_class: medium - steps: - - checkout - - attach_workspace: { at: "." } - - install-contracts-dependencies - - check-changed: - patterns: contracts-bedrock - - run: - name: validate spacers - command: just validate-spacers-no-build - working_directory: packages/contracts-bedrock + command: validate-spacers-no-build todo-issues: parameters: @@ -1366,9 +1355,6 @@ workflows: - contracts-bedrock-checks: requires: - contracts-bedrock-build - - contracts-bedrock-validate-spacers: - requires: - - contracts-bedrock-build - semgrep-scan: name: semgrep-scan-local scan_command: semgrep scan --timeout=100 --config .semgrep/rules/ --error . From 38db65294e86b8edf98468cfd9f9d030e709f03f Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 22 Nov 2024 13:31:32 -0500 Subject: [PATCH 11/61] fix(ci): lint test names after running tests (#13037) Moves the task for linting test names to after the tests job so that the contract artifacts actually exist. We don't compile everything ahead of time and rely on forge test to do the compilation in an effort to cut down total compile time. --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 797e7f20655..74115994f47 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -684,10 +684,6 @@ jobs: name: Build go-ffi command: just build-go-ffi working_directory: packages/contracts-bedrock - - run: - name: Lint forge test names - command: just lint-forge-tests-check-no-build - working_directory: packages/contracts-bedrock - run: name: Run tests command: | @@ -707,6 +703,10 @@ jobs: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock when: on_fail + - run: + name: Lint forge test names + command: just lint-forge-tests-check-no-build + working_directory: packages/contracts-bedrock - save_cache: name: Save Go build cache key: golang-build-cache-contracts-bedrock-tests-{{ checksum "go.sum" }} From 43ccf8eab7f9745bb194f63b6edb5dbe9ea905d7 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 22 Nov 2024 19:45:12 +0100 Subject: [PATCH 12/61] add more tests (#13036) --- .../test/L1/L2OutputOracle.t.sol | 25 +++++++++++++++++++ .../test/L2/GasPriceOracle.t.sol | 20 +++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol index 490ae07c927..5719d3fa558 100644 --- a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol @@ -99,6 +99,31 @@ contract L2OutputOracle_getter_Test is L2OutputOracle_TestBase { l2OutputOracle.getL2Output(nextOutputIndex + 1); } + /// @dev Tests that `getL2OutputAfter` of an L2 block number returns the L2 output of the `getL2OutputIndexAfter` of + /// that block number. + function test_getL2OutputAfter_succeeds() external { + uint8 iterations = 5; + + Types.OutputProposal memory output; + Types.OutputProposal memory expectedOutput; + + for (uint8 i; i < iterations; i++) { + proposeAnotherOutput(); + } + + uint256 latestBlockNumber = l2OutputOracle.latestBlockNumber(); + for (uint8 i = iterations - 1; i > 0; i--) { + uint256 index = l2OutputOracle.getL2OutputIndexAfter(latestBlockNumber); + output = l2OutputOracle.getL2OutputAfter(latestBlockNumber); + expectedOutput = l2OutputOracle.getL2Output(index); + assertEq(output.outputRoot, expectedOutput.outputRoot); + assertEq(output.timestamp, expectedOutput.timestamp); + assertEq(output.l2BlockNumber, expectedOutput.l2BlockNumber); + + latestBlockNumber -= l2OutputOracle.SUBMISSION_INTERVAL(); + } + } + /// @dev Tests that `getL2OutputIndexAfter` returns the correct value /// when the input is the exact block number of the proposal. function test_getL2OutputIndexAfter_sameBlock_succeeds() external { diff --git a/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol b/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol index 0a1d97c9351..f013325ef7e 100644 --- a/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol +++ b/packages/contracts-bedrock/test/L2/GasPriceOracle.t.sol @@ -117,6 +117,26 @@ contract GasPriceOracleBedrock_Test is GasPriceOracle_Test { vm.expectRevert("GasPriceOracle: Fjord can only be activated after Ecotone"); gasPriceOracle.setFjord(); } + + /// @dev Tests that `getL1Fee` returns the expected value when both fjord and ecotone are not active + function test_getL1Fee_whenFjordAndEcotoneNotActive_succeeds() external { + vm.store(address(gasPriceOracle), bytes32(uint256(0)), bytes32(0)); + bytes memory data = hex"1111"; + + uint256 price = gasPriceOracle.getL1Fee(data); + assertEq(price, 28_600); // ((((16 * data.length(i.e 2)) * (68 * 16)) + l1FeeOverhead(i.e. 310)) * + // l1BaseFee(i.e. 2M) * + // l1FeeScalar(i.e. 10)) / 1e6 + } + + /// @dev Tests that `getL1GasUsed` returns the expected value when both fjord and ecotone are not active + function test_getL1GasUsed_whenFjordAndEcotoneNotActive_succeeds() external { + vm.store(address(gasPriceOracle), bytes32(uint256(0)), bytes32(0)); + bytes memory data = hex"1111"; + + uint256 gas = gasPriceOracle.getL1GasUsed(data); + assertEq(gas, 1_430); // 1398 + (16 * data.length(i.e 2)) + } } contract GasPriceOracleEcotone_Test is GasPriceOracle_Test { From 131320e47679f31c08a512c74123645b3a39171f Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Fri, 22 Nov 2024 13:45:17 -0500 Subject: [PATCH 13/61] feat: improve DeployerWhitelist tests (#13035) Co-authored-by: Michael Amadi --- .../test/legacy/DeployerWhitelist.t.sol | 105 +++++++++++++++++- .../test/legacy/L1BlockNumber.t.sol | 2 +- 2 files changed, 102 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol index 3f140e9a072..6d0abaea8d2 100644 --- a/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol +++ b/packages/contracts-bedrock/test/legacy/DeployerWhitelist.t.sol @@ -10,6 +10,11 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; contract DeployerWhitelist_Test is Test { IDeployerWhitelist list; + address owner = address(12345); + + event OwnerChanged(address oldOwner, address newOwner); + event WhitelistDisabled(address oldOwner); + event WhitelistStatusChanged(address deployer, bool whitelisted); /// @dev Sets up the test suite. function setUp() public { @@ -27,10 +32,102 @@ contract DeployerWhitelist_Test is Test { } /// @dev Tests that `setOwner` correctly sets the contract owner. - function test_storageSlots_succeeds() external { - vm.prank(list.owner()); - list.setOwner(address(1)); + function test_setOwner_succeeds(address _owner) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + _owner = address(uint160(bound(uint160(_owner), 1, type(uint160).max))); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit OwnerChanged(owner, _owner); + list.setOwner(_owner); + + assertEq(list.owner(), _owner); + } + + /// @dev Tests that `setOwner` reverts when the caller is not the owner. + function test_setOwner_callerNotOwner_reverts(address _caller, address _owner) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); + + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.setOwner(_owner); + } + + /// @dev Tests that `setOwner` reverts when the new owner is the zero address. + function test_setOwner_zeroAddress_reverts() external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectRevert(bytes("DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment")); + list.setOwner(address(0)); + } + + /// @dev Tests that `enableArbitraryContractDeployment` correctly disables the whitelist. + function test_enableArbitraryContractDeployment_succeeds() external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit WhitelistDisabled(owner); + list.enableArbitraryContractDeployment(); + + assertEq(list.owner(), address(0)); + + // Any address is allowed to deploy contracts even if they are not whitelisted + assertEq(list.whitelist(address(1)), false); + assertEq(list.isDeployerAllowed(address(1)), true); + } + + /// @dev Tests that `enableArbitraryContractDeployment` reverts when the caller is not the owner. + function test_enableArbitraryContractDeployment_callerNotOwner_reverts(address _caller) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); + + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.enableArbitraryContractDeployment(); + } + + /// @dev Tests that `setWhitelistedDeployer` correctly sets the whitelist status of a deployer. + function test_setWhitelistedDeployer_succeeds(address _deployer, bool _isWhitelisted) external { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.prank(owner); + vm.expectEmit(true, true, true, true); + emit WhitelistStatusChanged(_deployer, _isWhitelisted); + list.setWhitelistedDeployer(_deployer, _isWhitelisted); + + assertEq(list.whitelist(_deployer), _isWhitelisted); + + // _deployer is whitelisted or not (and arbitrary contract deployment is not enabled) + assertNotEq(list.owner(), address(0)); + assertEq(list.isDeployerAllowed(_deployer), _isWhitelisted); + } + + /// @dev Tests that `setWhitelistedDeployer` reverts when the caller is not the owner. + function test_setWhitelistedDeployer_callerNotOwner_reverts( + address _caller, + address _deployer, + bool _isWhitelisted + ) + external + { + vm.store(address(list), bytes32(uint256(0)), bytes32(uint256(uint160(owner)))); + assertEq(list.owner(), owner); + + vm.assume(_caller != owner); - assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0)))); + vm.prank(_caller); + vm.expectRevert(bytes("DeployerWhitelist: function can only be called by the owner of this contract")); + list.setWhitelistedDeployer(_deployer, _isWhitelisted); } } diff --git a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol index 49758739d2d..aa8d2545106 100644 --- a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol @@ -49,7 +49,7 @@ contract L1BlockNumberTest is Test { /// @dev Tests that `fallback` is correctly dispatched. function test_fallback_succeeds() external { - (bool success, bytes memory ret) = address(bn).call(hex""); + (bool success, bytes memory ret) = address(bn).call(hex"11"); assertEq(success, true); assertEq(ret, abi.encode(number)); } From 974ee6ff9f6c04086dd524f64cd59431f15c8eba Mon Sep 17 00:00:00 2001 From: Sebastian Stammler Date: Fri, 22 Nov 2024 20:11:44 +0100 Subject: [PATCH 14/61] ctb: Fix Holocene upgrade script (#13015) * ctb: Fix Holocene upgrade script * improve README * pass deploy-config as parameter to just run, other improvements * remove commented-out variables --- .../scripts/upgrades/holocene/.env.example | 8 +--- .../scripts/upgrades/holocene/README.md | 17 ++++++- .../scripts/upgrades/holocene/justfile | 11 +++-- .../scripts/upgrades/holocene/scripts/main.sh | 46 +++++++++---------- .../holocene/scripts/proofs-bundle.sh | 16 +++---- .../holocene/scripts/sc-ops-proofs.sh | 16 +++---- .../holocene/scripts/sc-ops-sys-cfg.sh | 8 ++-- .../holocene/scripts/sys-cfg-bundle.sh | 10 ++-- .../upgrades/holocene/upgrade.dockerfile | 3 ++ 9 files changed, 76 insertions(+), 59 deletions(-) diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example b/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example index 02d67a4bad0..2d7d84e67aa 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/.env.example @@ -2,6 +2,8 @@ # ↓ Required ↓ # ############################################## +# NOTE: The deploy config must be provided as a first argument to `just run`! + # The network to deploy the contracts to. # Must be one of 'mainnet', 'sepolia' NETWORK= @@ -15,12 +17,6 @@ ETH_RPC_URL= # Private key used to deploy the new contracts for this upgrade PRIVATE_KEY= -# Path to the deploy config JSON file -DEPLOY_CONFIG_PATH= - -# Path to the folder where output artifacts will be stored -OUTPUT_FOLDER_PATH= - # Address of deployed `PreimageOracle` contract. PREIMAGE_ORACLE_ADDR= diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/README.md b/packages/contracts-bedrock/scripts/upgrades/holocene/README.md index f16127ffebb..a671362bff8 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/README.md +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/README.md @@ -37,5 +37,20 @@ cp .env.example .env && vim .env # - Deploy the new smart contract implementations. # - Optionally, generate a safe upgrade bundle. # - Optionally, generate a `superchain-ops` upgrade task. -just run +# +# The first argument must be the absolute path to your deploy-config.json. +# You can optionally specify an output folder path different from the default `output/` as a +# second argument to `just run`, also as an absolute path. +just run $(realpath path/to/deploy-config.json) ``` + +Note that in order to build the Docker image, you have to allow Docker to use at least 16GB of +memory, or the Solidity compilations may fail. Docker's default is only 8GB. + +The `deploy-config.json` that you use for your chain must set the latest `faultGameAbsolutePrestate` +value, not the one at deployment. There's currently one available that includes the Sepolia +Superchain Holocene activations for Base, OP, Mode and Zora: +`0x03925193e3e89f87835bbdf3a813f60b2aa818a36bbe71cd5d8fd7e79f5e8afe` + +If you want to make local modifications to the scripts in `scripts/`, you need to build the Docker +image again with `just build-image` before running `just run`. diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/justfile b/packages/contracts-bedrock/scripts/upgrades/holocene/justfile index 08cdc771ac9..ac08df68132 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/justfile +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/justfile @@ -4,16 +4,19 @@ default: # Run the deployment / upgrade generation image. If the image is not present locally, # it will be built. -run *args='': +run deploy-config-path output-folder-path="$(pwd)/output/" *args='': #!/bin/bash if [ ! "$(docker images -q op-holocene-upgrade:local 2> /dev/null)" ]; then just build-image fi + mkdir -p {{output-folder-path}} + # Run the deployment. - docker run \ + docker run -it \ --rm \ - -v $OUTPUT_FOLDER_PATH/:/output \ + -v {{output-folder-path}}:/output \ + -v {{deploy-config-path}}:/app/packages/contracts-bedrock/deploy-config/deploy-config.json \ --env-file=.env \ op-holocene-upgrade:local {{args}} @@ -22,5 +25,5 @@ build-image: docker build \ -t op-holocene-upgrade:local \ -f upgrade.dockerfile \ - --build-arg REV=op-contracts/v1.8.0-rc.1 \ + --build-arg REV=op-contracts/v1.8.0-rc.2 \ . diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/main.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/main.sh index 95fe1a43c23..7ae6a55ed72 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/main.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/main.sh @@ -37,8 +37,7 @@ export NETWORK="${NETWORK:?NETWORK must be set}" export ETHERSCAN_API_KEY=${ETHERSCAN_API_KEY:?ETHERSCAN_API_KEY must be set} export ETH_RPC_URL=${ETH_RPC_URL:?ETH_RPC_URL must be set} export PRIVATE_KEY=${PRIVATE_KEY:?PRIVATE_KEY must be set} -export BASE_DEPLOY_CONFIG_PATH=${DEPLOY_CONFIG_PATH:?DEPLOY_CONFIG_PATH must be set} -export OUTPUT_FOLDER_PATH=${OUTPUT_FOLDER_PATH:?OUTPUT_FOLDER_PATH must be set} +export OUTPUT_FOLDER_PATH="/output" export SYSTEM_CONFIG_IMPL_ADDR=${SYSTEM_CONFIG_IMPL_ADDR:-$(fetch_standard_address "$NETWORK" "$RELEASE" "system_config")} export MIPS_IMPL_ADDR=${MIPS_IMPL_ADDR:-$(fetch_standard_address "$NETWORK" "$RELEASE" "mips")} export PREIMAGE_ORACLE_ADDR=${PREIMAGE_ORACLE_ADDR:?PREIMAGE_ORACLE_ADDR must be set} @@ -53,8 +52,8 @@ export USE_PERMISSIONLESS_FAULT_PROOFS=${USE_PERMISSIONLESS_FAULT_PROOFS:?USE_PE # Sanity check FP configuration. if [[ $USE_PERMISSIONLESS_FAULT_PROOFS == true && $USE_FAULT_PROOFS == false ]]; then - echo "Error: USE_PERMISSIONLESS_FAULT_PROOFS cannot be true if USE_FAULT_PROOFS is false" - exit 1 + echo "Error: USE_PERMISSIONLESS_FAULT_PROOFS cannot be true if USE_FAULT_PROOFS is false" + exit 1 fi # Make the output folder, if it doesn't exist @@ -63,26 +62,28 @@ mkdir -p "$OUTPUT_FOLDER_PATH" # Find the contracts-bedrock directory CONTRACTS_BEDROCK_DIR=$(pwd) while [[ "$CONTRACTS_BEDROCK_DIR" != "/" && "${CONTRACTS_BEDROCK_DIR##*/}" != "contracts-bedrock" ]]; do - CONTRACTS_BEDROCK_DIR=$(dirname "$CONTRACTS_BEDROCK_DIR") + CONTRACTS_BEDROCK_DIR=$(dirname "$CONTRACTS_BEDROCK_DIR") done # Error out if we couldn't find it for some reason if [[ "$CONTRACTS_BEDROCK_DIR" == "/" ]]; then - echo "Error: 'contracts-bedrock' directory not found" - exit 1 + echo "Error: 'contracts-bedrock' directory not found" + exit 1 fi -# Set file paths from command-line arguments +# The deploy config is mounted via Docker to this file export DEPLOY_CONFIG_PATH="$CONTRACTS_BEDROCK_DIR/deploy-config/deploy-config.json" -# Copy the files into the paths so that the script can actually access it -cp "$BASE_DEPLOY_CONFIG_PATH" "$DEPLOY_CONFIG_PATH" - -# Run deploy.sh +# Run deploy.sh if deployments.json does not exist DEPLOY_LOG_PATH="$OUTPUT_FOLDER_PATH/deploy.log" -if ! "$SCRIPT_DIR/deploy.sh" | tee "$DEPLOY_LOG_PATH"; then +DEPLOYMENTS_JSON_PATH="$OUTPUT_FOLDER_PATH/deployments.json" +if [[ ! -f "$DEPLOYMENTS_JSON_PATH" ]]; then + if ! "$SCRIPT_DIR/deploy.sh" | tee "$DEPLOY_LOG_PATH"; then echo "Error: deploy.sh failed" exit 1 + fi +else + prompt "Skipping deployment as $DEPLOYMENTS_JSON_PATH already exists. Continue?" fi # Extract the addresses from the deployment logs @@ -102,8 +103,7 @@ reqenv "FDG_IMPL" reqenv "PDG_IMPL" # Generate deployments.json with extracted addresses -DEPLOYMENTS_JSON_PATH="$OUTPUT_FOLDER_PATH/deployments.json" -cat << EOF > "$DEPLOYMENTS_JSON_PATH" +cat <"$DEPLOYMENTS_JSON_PATH" { "SystemConfig": "$SYSTEM_CONFIG_IMPL", "MIPS": "$MIPS_IMPL", @@ -121,16 +121,16 @@ prompt "Generate safe upgrade bundle for SystemConfig?" # Generate the system config upgrade bundle if ! "$SCRIPT_DIR/sys-cfg-bundle.sh"; then - echo "Error: sys-cfg-bundle.sh failed" - exit 1 + echo "Error: sys-cfg-bundle.sh failed" + exit 1 fi prompt "Generate superchain-ops upgrade task for SystemConfig upgrade bundle?" # Generate the superchain-ops upgrade task if ! "$SCRIPT_DIR/sc-ops-sys-cfg.sh"; then - echo "Error: sc-ops-sys-cfg.sh failed" - exit 1 + echo "Error: sc-ops-sys-cfg.sh failed" + exit 1 fi if [[ $USE_FAULT_PROOFS == true ]]; then @@ -138,15 +138,15 @@ if [[ $USE_FAULT_PROOFS == true ]]; then # Generate the proofs contracts' upgrade bundle if ! "$SCRIPT_DIR/proofs-bundle.sh"; then - echo "Error: proofs-bundle.sh failed" - exit 1 + echo "Error: proofs-bundle.sh failed" + exit 1 fi prompt "Generate superchain-ops upgrade task for proofs contracts upgrade bundle?" # Generate the superchain-ops upgrade task if ! "$SCRIPT_DIR/sc-ops-proofs.sh"; then - echo "Error: sc-ops-proofs.sh failed" - exit 1 + echo "Error: sc-ops-proofs.sh failed" + exit 1 fi fi diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/proofs-bundle.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/proofs-bundle.sh index 85295d3040f..bc0b0c7ff31 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/proofs-bundle.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/proofs-bundle.sh @@ -31,24 +31,24 @@ TX_1_PAYLOAD=$(cast calldata "setImplementation(uint32,address)" 1 "$PDG_IMPL") TX_2_PAYLOAD=$(cast calldata "setImplementation(uint32,address)" 0 "$FDG_IMPL") # Replace variables -sed -i '' "s/\$L1_CHAIN_ID/$L1_CHAIN_ID/g" "$BUNDLE_PATH" -sed -i '' "s/\$PDG_IMPL/$PDG_IMPL/g" "$BUNDLE_PATH" -sed -i '' "s/\$TX_1_PAYLOAD/$TX_1_PAYLOAD/g" "$BUNDLE_PATH" -sed -i '' "s/\$TX_2_PAYLOAD/$TX_2_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$L1_CHAIN_ID/$L1_CHAIN_ID/g" "$BUNDLE_PATH" +sed -i "s/\$PDG_IMPL/$PDG_IMPL/g" "$BUNDLE_PATH" +sed -i "s/\$TX_1_PAYLOAD/$TX_1_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$TX_2_PAYLOAD/$TX_2_PAYLOAD/g" "$BUNDLE_PATH" # Conditionally, if the FDG is being deployed, append the bundle extension if [ "$USE_PERMISSIONLESS_FAULT_PROOFS" == true ]; then echo "✨ USE_PERMISSIONLESS_FAULT_PROOFS=true | Adding FDG deployment to upgrade bundle." jq --argjson fdg_extension "$(cat ./templates/fdg_bundle_extension.json)" \ '.transactions += [$fdg_extension]' \ - "$BUNDLE_PATH" > "$BUNDLE_PATH.tmp" + "$BUNDLE_PATH" >"$BUNDLE_PATH.tmp" mv "$BUNDLE_PATH.tmp" "$BUNDLE_PATH" # Replace variables - sed -i '' "s/\$FDG_IMPL/$FDG_IMPL/g" "$BUNDLE_PATH" - sed -i '' "s/\$TX_2_PAYLOAD/$TX_2_PAYLOAD/g" "$BUNDLE_PATH" + sed -i "s/\$FDG_IMPL/$FDG_IMPL/g" "$BUNDLE_PATH" + sed -i "s/\$TX_2_PAYLOAD/$TX_2_PAYLOAD/g" "$BUNDLE_PATH" fi -sed -i '' "s/\$DISPUTE_GAME_FACTORY_PROXY_ADDR/$DISPUTE_GAME_FACTORY_PROXY_ADDR/g" "$BUNDLE_PATH" +sed -i "s/\$DISPUTE_GAME_FACTORY_PROXY_ADDR/$DISPUTE_GAME_FACTORY_PROXY_ADDR/g" "$BUNDLE_PATH" echo "✨ Generated proof contracts upgrade bundle at \"$BUNDLE_PATH\"" diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-proofs.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-proofs.sh index d4ff18db573..ec386727d3b 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-proofs.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-proofs.sh @@ -27,9 +27,9 @@ cp -R "$SCRIPT_DIR/../templates/proofs-sc-ops-task/." "$TASK_DIR/" msup render -i "$TASK_DIR/input.json" -o "$TASK_DIR/OVERVIEW.md" # Generate the README -sed -i '' "s/\$MIPS_IMPL/$MIPS_IMPL/g" "$TASK_DIR/README.md" -sed -i '' "s/\$FDG_IMPL/$FDG_IMPL/g" "$TASK_DIR/README.md" -sed -i '' "s/\$PDG_IMPL/$PDG_IMPL/g" "$TASK_DIR/README.md" +sed -i "s/\$MIPS_IMPL/$MIPS_IMPL/g" "$TASK_DIR/README.md" +sed -i "s/\$FDG_IMPL/$FDG_IMPL/g" "$TASK_DIR/README.md" +sed -i "s/\$PDG_IMPL/$PDG_IMPL/g" "$TASK_DIR/README.md" # Generate the validation doc OLD_FDG=$(cast call "$DISPUTE_GAME_FACTORY_PROXY_ADDR" "gameImpls(uint32)" 0) @@ -40,8 +40,8 @@ PADDED_OLD_PDG=$(cast 2u "$OLD_PDG") PADDED_FDG_IMPL=$(cast 2u "$FDG_IMPL") PADDED_PDG_IMPL=$(cast 2u "$PDG_IMPL") -sed -i '' "s/\$DISPUTE_GAME_FACTORY_PROXY_ADDR/$DISPUTE_GAME_FACTORY_PROXY_ADDR/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$OLD_FDG/$PADDED_OLD_FDG/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$FDG_IMPL/$PADDED_FDG_IMPL/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$PDG_IMPL/$PADDED_PDG_IMPL/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$OLD_PDG/$PADDED_OLD_PDG/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$DISPUTE_GAME_FACTORY_PROXY_ADDR/$DISPUTE_GAME_FACTORY_PROXY_ADDR/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$OLD_FDG/$PADDED_OLD_FDG/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$FDG_IMPL/$PADDED_FDG_IMPL/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$PDG_IMPL/$PADDED_PDG_IMPL/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$OLD_PDG/$PADDED_OLD_PDG/g" "$TASK_DIR/VALIDATION.md" diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh index b0e4a57b32b..a87de445d3d 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sc-ops-sys-cfg.sh @@ -25,7 +25,7 @@ cp -R "$SCRIPT_DIR/../templates/sys-cfg-sc-ops-task/." "$TASK_DIR/" msup render -i "$TASK_DIR/input.json" -o "$TASK_DIR/OVERVIEW.md" # Generate the README -sed -i '' "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$TASK_DIR/README.md" +sed -i "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$TASK_DIR/README.md" # Generate the validation doc OLD_SYS_CFG=$(cast impl "$SYSTEM_CONFIG_PROXY_ADDR") @@ -33,6 +33,6 @@ OLD_SYS_CFG=$(cast impl "$SYSTEM_CONFIG_PROXY_ADDR") PADDED_OLD_SYS_CFG=$(cast 2u "$OLD_SYS_CFG") PADDED_SYS_CFG=$(cast 2u "$SYSTEM_CONFIG_IMPL") -sed -i '' "s/\$SYSTEM_CONFIG_PROXY_ADDR/$SYSTEM_CONFIG_PROXY_ADDR/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$OLD_SYS_CFG/$PADDED_OLD_SYS_CFG/g" "$TASK_DIR/VALIDATION.md" -sed -i '' "s/\$SYSTEM_CONFIG_IMPL/$PADDED_SYS_CFG/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$SYSTEM_CONFIG_PROXY_ADDR/$SYSTEM_CONFIG_PROXY_ADDR/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$OLD_SYS_CFG/$PADDED_OLD_SYS_CFG/g" "$TASK_DIR/VALIDATION.md" +sed -i "s/\$SYSTEM_CONFIG_IMPL/$PADDED_SYS_CFG/g" "$TASK_DIR/VALIDATION.md" diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh index 64c34088ebf..bde4917e6b8 100755 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/scripts/sys-cfg-bundle.sh @@ -26,10 +26,10 @@ cp ./templates/sys_cfg_upgrade_bundle_template.json "$BUNDLE_PATH" TX_1_PAYLOAD=$(cast calldata "upgrade(address,address)" "$SYSTEM_CONFIG_PROXY_ADDR" "$SYSTEM_CONFIG_IMPL") # Replace variables -sed -i '' "s/\$L1_CHAIN_ID/$L1_CHAIN_ID/g" "$BUNDLE_PATH" -sed -i '' "s/\$PROXY_ADMIN_ADDR/$PROXY_ADMIN_ADDR/g" "$BUNDLE_PATH" -sed -i '' "s/\$SYSTEM_CONFIG_PROXY_ADDR/$SYSTEM_CONFIG_PROXY_ADDR/g" "$BUNDLE_PATH" -sed -i '' "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$BUNDLE_PATH" -sed -i '' "s/\$TX_1_PAYLOAD/$TX_1_PAYLOAD/g" "$BUNDLE_PATH" +sed -i "s/\$L1_CHAIN_ID/$L1_CHAIN_ID/g" "$BUNDLE_PATH" +sed -i "s/\$PROXY_ADMIN_ADDR/$PROXY_ADMIN_ADDR/g" "$BUNDLE_PATH" +sed -i "s/\$SYSTEM_CONFIG_PROXY_ADDR/$SYSTEM_CONFIG_PROXY_ADDR/g" "$BUNDLE_PATH" +sed -i "s/\$SYSTEM_CONFIG_IMPL/$SYSTEM_CONFIG_IMPL/g" "$BUNDLE_PATH" +sed -i "s/\$TX_1_PAYLOAD/$TX_1_PAYLOAD/g" "$BUNDLE_PATH" echo "✨ Generated SystemConfig upgrade bundle at \"$BUNDLE_PATH\"" diff --git a/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile b/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile index f91ff8dadd8..33166fe6e5a 100644 --- a/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile +++ b/packages/contracts-bedrock/scripts/upgrades/holocene/upgrade.dockerfile @@ -58,5 +58,8 @@ RUN forge script ./scripts/upgrades/holocene/DeployUpgrade.s.sol || true # Set the working directory to where upgrade.sh is located WORKDIR /app/packages/contracts-bedrock/scripts/upgrades/holocene +# allows to use modified local scripts +COPY scripts/*.sh ./scripts/ + # Set the entrypoint to the main.sh script ENTRYPOINT ["./scripts/main.sh"] From ec45fa68c6de5855ae938bca932a7e6bff2a8c5a Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 22 Nov 2024 21:25:42 +0100 Subject: [PATCH 15/61] improve drippie & faucet tests and coverage (#13040) * improve drippie & faucet tests and coverage * Update packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol Co-authored-by: smartcontracts * Update packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol Co-authored-by: smartcontracts --------- Co-authored-by: smartcontracts --- .../test/periphery/drippie/Drippie.t.sol | 18 +++++++----------- .../test/periphery/faucet/Faucet.t.sol | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/contracts-bedrock/test/periphery/drippie/Drippie.t.sol b/packages/contracts-bedrock/test/periphery/drippie/Drippie.t.sol index 0e6755b0e63..c5791e06868 100644 --- a/packages/contracts-bedrock/test/periphery/drippie/Drippie.t.sol +++ b/packages/contracts-bedrock/test/periphery/drippie/Drippie.t.sol @@ -16,10 +16,6 @@ import { SimpleStorage } from "test/mocks/SimpleStorage.sol"; contract TestDrippie is Drippie { constructor(address owner) Drippie(owner) { } - function dripStatus(string memory name) external view returns (Drippie.DripStatus) { - return drips[name].status; - } - function dripStateLast(string memory name) external view returns (uint256) { return drips[name].last; } @@ -131,12 +127,12 @@ contract Drippie_Test is Test { vm.prank(drippie.owner()); drippie.create(dripName, cfg); - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); Drippie.DripConfig memory config = drippie.dripConfig(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.PAUSED)); - assertEq(config.interval, cfg.interval); + assertEq(drippie.getDripInterval(dripName), cfg.interval); assertEq(config.reentrant, cfg.reentrant); assertEq(address(config.dripcheck), address(cfg.dripcheck)); assertEq(config.checkparams, cfg.checkparams); @@ -186,7 +182,7 @@ contract Drippie_Test is Test { address owner = drippie.owner(); { - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.PAUSED)); } @@ -198,7 +194,7 @@ contract Drippie_Test is Test { drippie.status(dripName, Drippie.DripStatus.ACTIVE); { - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.ACTIVE)); } @@ -210,7 +206,7 @@ contract Drippie_Test is Test { drippie.status(dripName, Drippie.DripStatus.PAUSED); { - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.PAUSED)); } } @@ -252,7 +248,7 @@ contract Drippie_Test is Test { drippie.status(dripName, Drippie.DripStatus.ARCHIVED); - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.ARCHIVED)); } @@ -463,7 +459,7 @@ contract Drippie_Test is Test { function test_not_active_reverts() external { _createDefaultDrip(dripName); - Drippie.DripStatus status = drippie.dripStatus(dripName); + Drippie.DripStatus status = drippie.getDripStatus(dripName); assertEq(uint256(status), uint256(Drippie.DripStatus.PAUSED)); vm.prank(drippie.owner()); diff --git a/packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol b/packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol index a0ef75f28d5..b5f156cf1a8 100644 --- a/packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol +++ b/packages/contracts-bedrock/test/periphery/faucet/Faucet.t.sol @@ -103,6 +103,24 @@ contract FaucetTest is Faucet_Initializer { assertEq(faucet.ADMIN(), faucetContractAdmin); } + function test_configure_whenAdmin_succeeds() external { + vm.startPrank(faucetContractAdmin); + faucet.configure(optimistNftFam, Faucet.ModuleConfig("OptimistNftModule", true, 1 days, 1 ether)); + + (string memory name, bool enabled, uint256 ttl, uint256 amount) = faucet.modules(optimistNftFam); + assertEq(name, "OptimistNftModule"); + assertEq(enabled, true); + assertEq(ttl, 1 days); + assertEq(amount, 1 ether); + + assertTrue(faucet.isModuleEnabled(optimistNftFam)); + } + + function test_configure_whenNotAdmin_reverts() external { + vm.expectRevert("Faucet: function can only be called by admin"); + faucet.configure(optimistNftFam, Faucet.ModuleConfig("OptimistNftModule", true, 1 days, 1 ether)); + } + function test_authAdmin_drip_succeeds() external { _enableFaucetAuthModules(); bytes32 nonce = faucetHelper.consumeNonce(); From 6a871c54512ebdb749f46ccb7d27b1b60510eba1 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Fri, 22 Nov 2024 13:30:28 -0700 Subject: [PATCH 16/61] ci: Lower no output timeout by default (#13039) Most of the time there's no output from our Go tests, it means there's a bug. Lowering the timeout here will reduce the amount of time we spend waiting for jobs to fail. For long-running tests like fault proofs, the value is configured at 20m since those tests take longer. --- .circleci/config.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 74115994f47..5d93297da0e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -876,6 +876,7 @@ jobs: at: "." - run: name: run tests + no_output_timeout: 5m command: | mkdir -p ./tmp/test-results && mkdir -p ./tmp/testlogs @@ -936,6 +937,10 @@ jobs: description: Indicates that slow tests should be skipped type: boolean default: false + no_output_timeout: + description: Timeout for running tests + type: string + default: 5m machine: true resource_class: <> steps: @@ -955,7 +960,7 @@ jobs: command: go tool dist list | grep mips - run: name: run tests - no_output_timeout: 20m + no_output_timeout: <> command: | mkdir -p ./tmp/testlogs mkdir -p ./tmp/test-results @@ -1635,6 +1640,7 @@ workflows: module: op-e2e target: test-cannon notify: true + no_output_timeout: 20m mentions: "@proofs-team" resource_class: ethereum-optimism/latitude-fps-1 requires: From 80465cd6c428d13166fce351741492f354621643 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 22 Nov 2024 23:06:38 +0100 Subject: [PATCH 17/61] add test for L1ChugSplashProxy (#13045) * add test for L1ChugSplashProxy * fixes * fixes --- .../test/legacy/L1ChugSplashProxy.t.sol | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol diff --git a/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol b/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol new file mode 100644 index 00000000000..04a73f4998a --- /dev/null +++ b/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.15; + +// Testing utilities +import { Test } from "forge-std/Test.sol"; + +// Target contract +import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; +import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; + +contract Owner { + bool public isUpgrading; + + function setIsUpgrading(bool _isUpgrading) public { + isUpgrading = _isUpgrading; + } +} + +contract Implementation { + function setCode(bytes memory) public pure returns (uint256) { + return 1; + } + + function setStorage(bytes32, bytes32) public pure returns (uint256) { + return 2; + } + + function setOwner(address) public pure returns (uint256) { + return 3; + } + + function getOwner() public pure returns (uint256) { + return 4; + } + + function getImplementation() public pure returns (uint256) { + return 5; + } +} + +contract L1ChugSplashProxy_Test is Test { + IL1ChugSplashProxy proxy; + address impl; + address owner = makeAddr("owner"); + address alice = makeAddr("alice"); + + function setUp() public { + proxy = IL1ChugSplashProxy( + DeployUtils.create1({ + _name: "L1ChugSplashProxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (owner))) + }) + ); + vm.prank(owner); + assertEq(proxy.getOwner(), owner); + + vm.prank(owner); + proxy.setCode(type(Implementation).runtimeCode); + + vm.prank(owner); + impl = proxy.getImplementation(); + } + + /// @notice Tests that the owner can deploy a new implementation with a given runtime code + function test_setCode_whenOwner_succeeds() public { + vm.prank(owner); + proxy.setCode(hex"604260005260206000f3"); + + vm.prank(owner); + assertNotEq(proxy.getImplementation(), impl); + } + + /// @notice Tests that when not the owner, `setCode` delegatecalls the implementation + function test_setCode_whenNotOwner_works() public view { + uint256 ret = Implementation(address(proxy)).setCode(hex"604260005260206000f3"); + assertEq(ret, 1); + } + + /// @notice Tests that when the owner deploys the same bytecode as the existing implementation, + /// it does not deploy a new implementation + function test_setCode_whenOwnerSameBytecode_works() public { + vm.prank(owner); + proxy.setCode(type(Implementation).runtimeCode); + + // does not deploy new implementation + vm.prank(owner); + assertEq(proxy.getImplementation(), impl); + } + + /// @notice Tests that when the owner calls `setCode` with insufficient gas to complete the implementation + /// contract's deployment, it reverts. + /// @dev If this solc version/settings change and modifying this proves time consuming, we can just remove it. + function test_setCode_whenOwnerAndDeployOutOfGas_reverts() public { + vm.prank(owner); + vm.expectRevert(bytes("L1ChugSplashProxy: code was not correctly deployed")); // Ran out of gas + proxy.setCode{ gas: 65_000 }( + hex"fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe" + ); + } + + /// @notice Tests that when the caller is not the owner and the implementation is not set, all calls reverts + function test_calls_whenNotOwnerNoImplementation_reverts() public { + proxy = IL1ChugSplashProxy( + DeployUtils.create1({ + _name: "L1ChugSplashProxy", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (owner))) + }) + ); + + vm.expectRevert(bytes("L1ChugSplashProxy: implementation is not set yet")); + Implementation(address(proxy)).setCode(hex"604260005260206000f3"); + } + + /// @notice Tests that when the caller is not the owner but the owner has marked `isUpgrading` as true, the call + /// reverts + function test_calls_whenUpgrading_reverts() public { + Owner ownerContract = new Owner(); + vm.prank(owner); + proxy.setOwner(address(ownerContract)); + + ownerContract.setIsUpgrading(true); + + vm.expectRevert(bytes("L1ChugSplashProxy: system is currently being upgraded")); + Implementation(address(proxy)).setCode(hex"604260005260206000f3"); + } + + /// @notice Tests that the owner can set storage of the proxy + function test_setStorage_whenOwner_works() public { + vm.prank(owner); + proxy.setStorage(bytes32(0), bytes32(uint256(42))); + assertEq(vm.load(address(proxy), bytes32(0)), bytes32(uint256(42))); + } + + /// @notice Tests that when not the owner, `setStorage` delegatecalls the implementation + function test_setStorage_whenNotOwner_works() public view { + uint256 ret = Implementation(address(proxy)).setStorage(bytes32(0), bytes32(uint256(42))); + assertEq(ret, 2); + assertEq(vm.load(address(proxy), bytes32(0)), bytes32(uint256(0))); + } + + /// @notice Tests that the owner can set the owner of the proxy + function test_setOwner_whenOwner_works() public { + vm.prank(owner); + proxy.setOwner(alice); + + vm.prank(alice); + assertEq(proxy.getOwner(), alice); + } + + /// @notice Tests that when not the owner, `setOwner` delegatecalls the implementation + function test_setOwner_whenNotOwner_works() public { + uint256 ret = Implementation(address(proxy)).setOwner(alice); + assertEq(ret, 3); + + vm.prank(owner); + assertEq(proxy.getOwner(), owner); + } + + /// @notice Tests that the owner can get the owner of the proxy + function test_getOwner_whenOwner_works() public { + vm.prank(owner); + assertEq(proxy.getOwner(), owner); + } + + /// @notice Tests that when not the owner, `getOwner` delegatecalls the implementation + function test_getOwner_whenNotOwner_works() public view { + uint256 ret = Implementation(address(proxy)).getOwner(); + assertEq(ret, 4); + } + + /// @notice Tests that the owner can get the implementation of the proxy + function test_getImplementation_whenOwner_works() public { + vm.prank(owner); + assertEq(proxy.getImplementation(), impl); + } + + /// @notice Tests that when not the owner, `getImplementation` delegatecalls the implementation + function test_getImplementation_whenNotOwner_works() public view { + uint256 ret = Implementation(address(proxy)).getImplementation(); + assertEq(ret, 5); + } +} From 44367b028fea19bebbc34daf16d68b549ce35105 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Sat, 23 Nov 2024 16:33:33 +0100 Subject: [PATCH 18/61] add LegacyMintableERC20 tests (#13049) * add LegacyMintableERC20 tests * fixes --- .../test/legacy/LegacyMintableERC20.t.sol | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/contracts-bedrock/test/legacy/LegacyMintableERC20.t.sol diff --git a/packages/contracts-bedrock/test/legacy/LegacyMintableERC20.t.sol b/packages/contracts-bedrock/test/legacy/LegacyMintableERC20.t.sol new file mode 100644 index 00000000000..061b6eee6c5 --- /dev/null +++ b/packages/contracts-bedrock/test/legacy/LegacyMintableERC20.t.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing utilities +import { CommonTest } from "test/setup/CommonTest.sol"; + +import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol"; +import { ILegacyMintableERC20 } from "src/universal/interfaces/ILegacyMintableERC20.sol"; + +contract LegacyMintableERC20_Test is CommonTest { + LegacyMintableERC20 legacyMintableERC20; + + function setUp() public override { + super.setUp(); + + legacyMintableERC20 = new LegacyMintableERC20(address(l2StandardBridge), address(L1Token), "_L2Token_", "_L2T_"); + } + + /// @notice Tests that the constructor sets the correct values + function test_constructor_works() public view { + assertEq(legacyMintableERC20.l2Bridge(), address(l2StandardBridge)); + assertEq(legacyMintableERC20.l1Token(), address(L1Token)); + assertEq(legacyMintableERC20.name(), "_L2Token_"); + assertEq(legacyMintableERC20.symbol(), "_L2T_"); + assertEq(legacyMintableERC20.decimals(), 18); + } + + /// @notice Tests that the contract supports the correct interfaces + function test_supportsInterface_works() public view { + assertEq(legacyMintableERC20.supportsInterface(bytes4(keccak256("supportsInterface(bytes4)"))), true); + assertEq( + legacyMintableERC20.supportsInterface( + ILegacyMintableERC20.l1Token.selector ^ ILegacyMintableERC20.mint.selector + ^ ILegacyMintableERC20.burn.selector + ), + true + ); + } + + /// @notice Tests that the mint function works when called by the bridge + function test_mint_byBridge_succeeds() public { + vm.prank(address(l2StandardBridge)); + legacyMintableERC20.mint(address(this), 1000); + assertEq(legacyMintableERC20.balanceOf(address(this)), 1000); + } + + /// @notice Tests that the mint function fails when called by an address other than the bridge + function test_mint_byNonBridge_reverts() public { + vm.expectRevert(bytes("Only L2 Bridge can mint and burn")); + legacyMintableERC20.mint(address(this), 1000); + } + + /// @notice Tests that the burn function works when called by the bridge + function test_burn_byBridge_succeeds() public { + vm.prank(address(l2StandardBridge)); + legacyMintableERC20.mint(address(this), 1000); + + vm.prank(address(l2StandardBridge)); + legacyMintableERC20.burn(address(this), 1000); + assertEq(legacyMintableERC20.balanceOf(address(this)), 0); + } + + /// @notice Tests that the burn function fails when called by an address other than the bridge + function test_burn_byNonBridge_reverts() public { + vm.expectRevert(bytes("Only L2 Bridge can mint and burn")); + legacyMintableERC20.burn(address(this), 1000); + } +} From 7719c8538b8d911519f861fc70085e7a3b4e6787 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Sun, 24 Nov 2024 19:44:02 +0100 Subject: [PATCH 19/61] fixes (#13052) --- .../test/legacy/L1ChugSplashProxy.t.sol | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol b/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol index 04a73f4998a..dcfab12cb60 100644 --- a/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1ChugSplashProxy.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"; // Target contract import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; @@ -91,9 +92,28 @@ contract L1ChugSplashProxy_Test is Test { /// contract's deployment, it reverts. /// @dev If this solc version/settings change and modifying this proves time consuming, we can just remove it. function test_setCode_whenOwnerAndDeployOutOfGas_reverts() public { + // The values below are best gotten by removing the gas limit parameter from the call and running the test with + // a + // verbosity of `-vvvv` then setting the value to a few thousand gas lower than the gas used by the call. + // 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 gasLimit; + + // 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)) { + gasLimit = 95_000; + } else if (vm.isContext(VmSafe.ForgeContext.Test) || vm.isContext(VmSafe.ForgeContext.Snapshot)) { + gasLimit = 65_000; + } else { + revert("SafeCall_Test: unknown context"); + } + vm.prank(owner); vm.expectRevert(bytes("L1ChugSplashProxy: code was not correctly deployed")); // Ran out of gas - proxy.setCode{ gas: 65_000 }( + proxy.setCode{ gas: gasLimit }( hex"fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe" ); } From 418f0cca260789a359dcd2d19fa7fa44cceda085 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 25 Nov 2024 10:06:07 -0700 Subject: [PATCH 20/61] ci: Convert all Go tests into a single job (#13046) * ci: Convert all Go tests into a single job Takes all the go-e2e and go-test jobs and combines them into one single super-job. This has the following benefits: 1. We can centralize all config for Go tests in one place and simplify our CI pipeline. 2. It leaves parallelism up to the Go runtime, which is more efficient. 4. It makes our test reporting more accurate. As part of this PR, I also: 1. Created a new resource class just for Go tests. It runs on the large Latitude runner, but limits the number of parallel go test jobs to 3 to prevent resource starvation. 2. Enabled test retries on `gotestsum`. This should reduce the number of flakes we see from the Go tests by retrying them up to 2 times in the event that they fail. Failures are still captured by the test reporting, so we can address them. * code review updates --- .circleci/config.yml | 180 +++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 117 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5d93297da0e..8bba906ec4e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -867,60 +867,8 @@ jobs: path: tmp/testlogs when: always - go-test: - machine: true - resource_class: ethereum-optimism/latitude-1 - steps: - - checkout - - attach_workspace: - at: "." - - run: - name: run tests - no_output_timeout: 5m - command: | - mkdir -p ./tmp/test-results && mkdir -p ./tmp/testlogs - - packages=( - op-batcher - op-chain-ops - op-node - op-proposer - op-challenger - op-dispute-mon - op-conductor - op-program - op-service - op-supervisor - op-deployer - ) - formatted_packages="" - for package in "${packages[@]}"; do - formatted_packages="$formatted_packages ./$package/..." - done - - export ENABLE_ANVIL=true - export SEPOLIA_RPC_URL="https://ci-sepolia-l1-archive.optimism.io" - export MAINNET_RPC_URL="https://ci-mainnet-l1-archive.optimism.io" - - gotestsum --format=testname \ - --junitfile=./tmp/test-results/results.xml \ - --jsonfile=./tmp/testlogs/log.json \ - -- -coverpkg=github.com/ethereum-optimism/optimism/... \ - -coverprofile=coverage.out $formatted_packages - - store_test_results: - path: ./tmp/test-results - - store_artifacts: - path: ./tmp/testlogs - when: always - - go-e2e-test: + go-tests: parameters: - module: - description: Go Module Name - type: string - target: - description: The make target to execute - type: string notify: description: Whether to notify on failure type: boolean @@ -932,56 +880,60 @@ jobs: resource_class: description: Machine resource class type: string - default: ethereum-optimism/latitude-1 - skip_slow_tests: - description: Indicates that slow tests should be skipped - type: boolean - default: false + default: ethereum-optimism/latitude-1-go-e2e no_output_timeout: description: Timeout for running tests type: string default: 5m + environment_overrides: + description: Environment overrides + type: string + default: "" + packages: + description: List of packages to test + type: string machine: true resource_class: <> steps: - checkout - attach_workspace: - at: ./tmp/workspace - - run: - name: Load devnet-allocs and artifacts - command: | - mkdir -p .devnet - cp -r ./tmp/workspace/.devnet* . - cp -r ./tmp/workspace/packages/contracts-bedrock/forge-artifacts packages/contracts-bedrock/forge-artifacts - cp ./tmp/workspace/packages/contracts-bedrock/deploy-config/devnetL1.json packages/contracts-bedrock/deploy-config/devnetL1.json - cp -r ./tmp/workspace/packages/contracts-bedrock/deployments/devnetL1 packages/contracts-bedrock/deployments/devnetL1 - - run: - name: print go's available MIPS targets - command: go tool dist list | grep mips + at: "." - run: name: run tests no_output_timeout: <> command: | - mkdir -p ./tmp/testlogs - mkdir -p ./tmp/test-results + mkdir -p ./tmp/test-results && mkdir -p ./tmp/testlogs + + cd op-e2e && make pre-test && cd .. + + packages=( + <> + ) + formatted_packages="" + for package in "${packages[@]}"; do + formatted_packages="$formatted_packages ./$package/..." + done - # The below env var gets overridden when running make test-cannon, but we - # need to explicitly set it here to prevent Cannon from running when we don't - # want it to. export OP_E2E_CANNON_ENABLED="false" - export OP_E2E_SKIP_SLOW_TEST=<> - # Note: We don't use circle CI test splits because we need to split by test name, not by package. There is an additional - # constraint that gotestsum does not currently (nor likely will) accept files from different packages when building. - JUNIT_FILE=../tmp/test-results/<>_<>.xml JSON_LOG_FILE=../tmp/testlogs/test.log make <> - working_directory: <> + export OP_E2E_SKIP_SLOW_TEST=true + export OP_E2E_USE_HTTP=true + export ENABLE_ANVIL=true + export SEPOLIA_RPC_URL="https://ci-sepolia-l1-archive.optimism.io" + export MAINNET_RPC_URL="https://ci-mainnet-l1-archive.optimism.io" + + <> + + gotestsum --format=testname \ + --junitfile=./tmp/test-results/results.xml \ + --jsonfile=./tmp/testlogs/log.json \ + --rerun-fails=2 \ + --packages="$formatted_packages" \ + -- -coverprofile=coverage.out + - store_test_results: + path: ./tmp/test-results - store_artifacts: path: ./tmp/testlogs when: always - - store_artifacts: - path: ./tmp/test-results - when: always - - store_test_results: - path: ./tmp/test-results - when: condition: "<>" steps: @@ -1389,33 +1341,31 @@ workflows: on_changes: op-e2e,packages/contracts-bedrock/src uses_artifacts: true requires: ["contracts-bedrock-build"] - - go-test: - name: go-test-all - requires: - - contracts-bedrock-build - go-test-kurtosis: name: op-deployer-integration module: op-deployer test_directory: ./pkg/deployer/integration_test uses_artifacts: true requires: ["contracts-bedrock-build"] - - go-e2e-test: - name: op-e2e-HTTP-tests - module: op-e2e - target: test-http - requires: - - contracts-bedrock-build - - go-e2e-test: - name: op-e2e-action-tests - module: op-e2e - target: test-actions - requires: - - contracts-bedrock-build - - go-e2e-test: - name: op-e2e-fault-proof-tests - module: op-e2e - target: test-fault-proofs - skip_slow_tests: true + - go-tests: + packages: | + op-batcher + op-chain-ops + op-node + op-proposer + op-challenger + op-dispute-mon + op-conductor + op-program + op-service + op-supervisor + op-deployer + op-e2e/system + op-e2e/e2eutils + op-e2e/opgeth + op-e2e/interop + op-e2e/actions + op-e2e/faultproofs requires: - contracts-bedrock-build - cannon-prestate @@ -1432,16 +1382,13 @@ workflows: - go-mod-download - op-deployer-integration - op-program-compat - - op-e2e-HTTP-tests - - op-e2e-fault-proof-tests - - op-e2e-action-tests # Not needed for the devnet but we want to make sure they build successfully - cannon-docker-build - op-dispute-mon-docker-build - op-program-docker-build - op-supervisor-docker-build - proofs-tools-docker-build - - go-test-all + - go-tests - docker-build: name: <>-docker-build docker_tags: <>,<> @@ -1635,17 +1582,16 @@ workflows: skip_pattern: test context: - slack - - go-e2e-test: + - go-tests: name: op-e2e-cannon-tests - module: op-e2e - target: test-cannon notify: true - no_output_timeout: 20m mentions: "@proofs-team" + no_output_timeout: 20m resource_class: ethereum-optimism/latitude-fps-1 - requires: - - contracts-bedrock-build - - cannon-prestate + environment_overrides: | + export OP_E2E_CANNON_ENABLED="true" + packages: | + op-e2e/faultproofs context: - slack From 816b75a8e04ecdb10bfd0fedbcb287f2bbd9c820 Mon Sep 17 00:00:00 2001 From: Mael Regnery Date: Mon, 25 Nov 2024 18:19:21 +0100 Subject: [PATCH 21/61] fix: use eth_getBlockReceipts for Infura RPC kind (#12969) * fix: use eth_getBlockReceipts for Infura RPC kind * fix infura test --- op-service/sources/receipts_rpc.go | 3 +-- op-service/sources/receipts_test.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/op-service/sources/receipts_rpc.go b/op-service/sources/receipts_rpc.go index ecf2c858221..962c7391a76 100644 --- a/op-service/sources/receipts_rpc.go +++ b/op-service/sources/receipts_rpc.go @@ -329,8 +329,7 @@ func AvailableReceiptsFetchingMethods(kind RPCProviderKind) ReceiptsFetchingMeth case RPCKindQuickNode: return DebugGetRawReceipts | EthGetBlockReceipts | EthGetTransactionReceiptBatch case RPCKindInfura: - // Infura is big, but sadly does not support more optimized receipts fetching methods (yet?) - return EthGetTransactionReceiptBatch + return EthGetBlockReceipts | EthGetTransactionReceiptBatch case RPCKindParity: return ParityGetBlockReceipts | EthGetTransactionReceiptBatch case RPCKindNethermind: diff --git a/op-service/sources/receipts_test.go b/op-service/sources/receipts_test.go index 088a3d9b22c..230fcf0e72b 100644 --- a/op-service/sources/receipts_test.go +++ b/op-service/sources/receipts_test.go @@ -283,7 +283,7 @@ func TestEthClient_FetchReceipts(t *testing.T) { { name: "infura", providerKind: RPCKindInfura, - setup: fallbackCase(4, EthGetTransactionReceiptBatch), + setup: fallbackCase(4, EthGetBlockReceipts, EthGetTransactionReceiptBatch), }, { name: "nethermind", From c1731a54054c7363b653becbdbca6ba22c2d3623 Mon Sep 17 00:00:00 2001 From: Inphi Date: Mon, 25 Nov 2024 10:33:09 -0800 Subject: [PATCH 22/61] cannon: Bump step count for 64-bit map_test (#13065) --- cannon/mipsevm/multithreaded/instrumented_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cannon/mipsevm/multithreaded/instrumented_test.go b/cannon/mipsevm/multithreaded/instrumented_test.go index 6add2cc020a..659a5b7a5c2 100644 --- a/cannon/mipsevm/multithreaded/instrumented_test.go +++ b/cannon/mipsevm/multithreaded/instrumented_test.go @@ -157,7 +157,7 @@ func TestInstrumentedState_MultithreadedProgram(t *testing.T) { "Map test passed", }, programName: "mt-map", - steps: 100_000_000, + steps: 150_000_000, }, { name: "pool test", From cff136196c497cb4c97ddb8fe925166b1e58f268 Mon Sep 17 00:00:00 2001 From: chuangjinglu Date: Tue, 26 Nov 2024 02:40:48 +0800 Subject: [PATCH 23/61] chore: fix some function names in interface comment (#13048) Signed-off-by: chuangjinglu --- op-conductor/consensus/iface.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op-conductor/consensus/iface.go b/op-conductor/consensus/iface.go index e0dcb6efd5a..2de955c1201 100644 --- a/op-conductor/consensus/iface.go +++ b/op-conductor/consensus/iface.go @@ -72,9 +72,9 @@ type Consensus interface { // ClusterMembership returns the current cluster membership configuration and associated version. ClusterMembership() (*ClusterMembership, error) - // CommitPayload commits latest unsafe payload to the FSM in a strongly consistent fashion. + // CommitUnsafePayload commits latest unsafe payload to the FSM in a strongly consistent fashion. CommitUnsafePayload(payload *eth.ExecutionPayloadEnvelope) error - // LatestUnsafeBlock returns the latest unsafe payload from FSM in a strongly consistent fashion. + // LatestUnsafePayload returns the latest unsafe payload from FSM in a strongly consistent fashion. LatestUnsafePayload() (*eth.ExecutionPayloadEnvelope, error) // Shutdown shuts down the consensus protocol client. From ea7f56c519f2e536fcbbcc26300cce5ecce0926c Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 25 Nov 2024 12:36:17 -0700 Subject: [PATCH 24/61] ci: Increase test timeout (#13067) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8bba906ec4e..789ce0b8c56 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -928,7 +928,7 @@ jobs: --jsonfile=./tmp/testlogs/log.json \ --rerun-fails=2 \ --packages="$formatted_packages" \ - -- -coverprofile=coverage.out + -- -coverprofile=coverage.out -timeout=60m - store_test_results: path: ./tmp/test-results - store_artifacts: From 8f69ac78712d89b1dd018efa09e1edfc97a75314 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 25 Nov 2024 15:00:19 -0700 Subject: [PATCH 25/61] op-deployer: Add a proxy to handle RPC failures (#13068) * op-deployer: Add a proxy to handle RPC failures Anvil is very finnicky when it comes to RPC responses. It'll blow up if it encounters any HTTP error, and does not support retries. This PR adds a locally-hosted proxy which sits between Anvil and the fork RPC source and handles retries automatically. * lint * lint again * ignore lint --- .../deployer/integration_test/apply_test.go | 10 +- op-e2e/e2eutils/retryproxy/proxy.go | 160 ++++++++++++++++++ 2 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 op-e2e/e2eutils/retryproxy/proxy.go diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index f977fbbb0c7..682aaccfbc0 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -16,6 +16,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/retryproxy" + altda "github.com/ethereum-optimism/optimism/op-alt-da" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -195,8 +197,14 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() + retryProxy := retryproxy.New(lgr, forkRPCUrl) + require.NoError(t, retryProxy.Start()) + t.Cleanup(func() { + require.NoError(t, retryProxy.Stop()) + }) + runner, err := anvil.New( - forkRPCUrl, + retryProxy.Endpoint(), lgr, ) require.NoError(t, err) diff --git a/op-e2e/e2eutils/retryproxy/proxy.go b/op-e2e/e2eutils/retryproxy/proxy.go new file mode 100644 index 00000000000..a74d5d8c869 --- /dev/null +++ b/op-e2e/e2eutils/retryproxy/proxy.go @@ -0,0 +1,160 @@ +package retryproxy + +import ( + "bytes" + "context" + "fmt" + "io" + "net" + "net/http" + "time" + + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum/go-ethereum/log" +) + +var copyHeaders = []string{ + "Content-Type", +} + +type RetryProxy struct { + lgr log.Logger + upstream string + client *http.Client + strategy retry.Strategy + maxRetries int + srv *http.Server + listenPort int +} + +type Option func(*RetryProxy) + +func New(lgr log.Logger, upstream string, opts ...Option) *RetryProxy { + strategy := &retry.ExponentialStrategy{ + Min: 250 * time.Millisecond, + Max: 5 * time.Second, + MaxJitter: 250 * time.Millisecond, + } + + prox := &RetryProxy{ + lgr: lgr.New("module", "retryproxy"), + upstream: upstream, + client: &http.Client{}, + strategy: strategy, + maxRetries: 5, + } + + for _, opt := range opts { + opt(prox) + } + + return prox +} + +func (p *RetryProxy) Start() error { + errC := make(chan error, 1) + + go func() { + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + errC <- fmt.Errorf("failed to listen: %w", err) + } + + p.listenPort = ln.Addr().(*net.TCPAddr).Port + + p.srv = &http.Server{ + Addr: "127.0.0.1:0", + Handler: p, + } + errC <- p.srv.Serve(ln) + }() + + timer := time.NewTimer(100 * time.Millisecond) + select { + case err := <-errC: + return fmt.Errorf("failed to start server: %w", err) + case <-timer.C: + p.lgr.Info("server started", "port", p.listenPort) + return nil + } +} + +func (p *RetryProxy) Stop() error { + if p.srv == nil { + return nil + } + + return p.srv.Shutdown(context.Background()) +} + +func (p *RetryProxy) Endpoint() string { + return fmt.Sprintf("http://127.0.0.1:%d", p.listenPort) +} + +func (p *RetryProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + defer r.Body.Close() + reqBody, err := io.ReadAll(r.Body) + if err != nil { + p.lgr.Error("failed to read request body", "err", err) + http.Error(w, "failed to read request body", http.StatusInternalServerError) + return + } + + //nolint:bodyClose + res, resBody, err := retry.Do2(r.Context(), p.maxRetries, p.strategy, func() (*http.Response, []byte, error) { + ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) + defer cancel() + res, err := p.doProxyReq(ctx, reqBody) + if err != nil { + p.lgr.Warn("failed to proxy request", "err", err) + return nil, nil, err + } + + defer res.Body.Close() + resBody, err := io.ReadAll(res.Body) + if err != nil { + p.lgr.Warn("failed to read response body", "err", err) + return nil, nil, err + } + + return res, resBody, nil + }) + if err != nil { + p.lgr.Error("permanently failed to proxy request", "err", err) + http.Error(w, "failed to proxy request", http.StatusBadGateway) + return + } + + for _, h := range copyHeaders { + w.Header().Set(h, res.Header.Get(h)) + } + + w.WriteHeader(http.StatusOK) + if _, err := io.Copy(w, bytes.NewReader(resBody)); err != nil { + p.lgr.Error("failed to copy response", "err", err) + http.Error(w, "failed to copy response", http.StatusInternalServerError) + } +} + +func (p *RetryProxy) doProxyReq(ctx context.Context, body []byte) (*http.Response, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.upstream, bytes.NewReader(body)) + if err != nil { + panic(fmt.Errorf("failed to create request: %w", err)) + } + res, err := p.client.Do(req) + if err != nil { + p.lgr.Warn("failed to proxy request", "err", err) + return nil, err + } + status := res.StatusCode + if status != 200 { + p.lgr.Warn("unexpected status code", "status", status) + return nil, fmt.Errorf("unexpected status code: %d", status) + } + return res, nil +} From cf83fd94ca1cd7c03164b2066ba04606c3fd34d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:00:28 -0700 Subject: [PATCH 26/61] dependabot(gomod): bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#13075) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 5454732a74a..ef2c5bee53e 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/pkg/profile v1.7.0 github.com/prometheus/client_golang v1.20.5 github.com/protolambda/ctxlock v0.1.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/urfave/cli/v2 v2.27.5 golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c diff --git a/go.sum b/go.sum index 60b90554c2e..12ffc499453 100644 --- a/go.sum +++ b/go.sum @@ -778,8 +778,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= From ce751a0119281e0fdd3786cf617ab989100531ec Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 25 Nov 2024 17:20:54 -0500 Subject: [PATCH 27/61] feat: delete unused deploy functions (#13083) * feat: delete unused deploy functions * feat: Delete some more unused code * fix: Unused imports --- .../scripts/deploy/Deploy.s.sol | 211 +----------------- 1 file changed, 1 insertion(+), 210 deletions(-) diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 6dc6a8bb90b..bfe062370a6 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -25,7 +25,6 @@ import { } from "scripts/deploy/DeployImplementations.s.sol"; // Contracts -import { StorageSetter } from "src/universal/StorageSetter.sol"; import { OPContractsManager } from "src/L1/OPContractsManager.sol"; // Libraries @@ -44,8 +43,6 @@ import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; -import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; -import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; import { ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; @@ -54,11 +51,7 @@ import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol" import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IMIPS } from "src/cannon/interfaces/IMIPS.sol"; -import { IMIPS2 } from "src/cannon/interfaces/IMIPS2.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; -import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; -import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; -import { IResolvedDelegateProxy } from "src/legacy/interfaces/IResolvedDelegateProxy.sol"; /// @title Deploy /// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function. @@ -502,102 +495,10 @@ contract Deploy is Deployer { initializeDataAvailabilityChallenge(); } - //////////////////////////////////////////////////////////////// - // Non-Proxied Deployment Functions // - //////////////////////////////////////////////////////////////// - - /// @notice Deploy the AddressManager - function deployAddressManager() public broadcast returns (address addr_) { - // Use create instead of create2 because we need the owner to be set to msg.sender but - // forge will automatically use the create2 factory which messes up the sender. - IAddressManager manager = IAddressManager( - DeployUtils.create1AndSave({ - _save: this, - _name: "AddressManager", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IAddressManager.__constructor__, ())) - }) - ); - require(manager.owner() == msg.sender); - addr_ = address(manager); - } - - /// @notice Deploys the ProxyAdmin contract. Should NOT be used for the Superchain. - function deployProxyAdmin() public broadcast returns (address addr_) { - // Deploy the ProxyAdmin contract. - IProxyAdmin admin = IProxyAdmin( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "ProxyAdmin", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IProxyAdmin.__constructor__, (msg.sender))) - }) - ); - - // Make sure the owner was set to the deployer. - require(admin.owner() == msg.sender); - - // Set the address manager if it is not already set. - IAddressManager addressManager = IAddressManager(mustGetAddress("AddressManager")); - if (admin.addressManager() != addressManager) { - admin.setAddressManager(addressManager); - } - - // Make sure the address manager is set properly. - require(admin.addressManager() == addressManager); - - // Return the address of the deployed contract. - addr_ = address(admin); - } - - /// @notice Deploy the StorageSetter contract, used for upgrades. - function deployStorageSetter() public broadcast returns (address addr_) { - console.log("Deploying StorageSetter"); - StorageSetter setter = new StorageSetter{ salt: _implSalt() }(); - console.log("StorageSetter deployed at: %s", address(setter)); - string memory version = setter.version(); - console.log("StorageSetter version: %s", version); - addr_ = address(setter); - } - //////////////////////////////////////////////////////////////// // Proxy Deployment Functions // //////////////////////////////////////////////////////////////// - /// @notice Deploy the L1StandardBridgeProxy using a ChugSplashProxy - function deployL1StandardBridgeProxy() public broadcast returns (address addr_) { - address proxyAdmin = mustGetAddress("ProxyAdmin"); - IL1ChugSplashProxy proxy = IL1ChugSplashProxy( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "L1ChugSplashProxy", - _nick: "L1StandardBridgeProxy", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (proxyAdmin))) - }) - ); - require(EIP1967Helper.getAdmin(address(proxy)) == proxyAdmin); - addr_ = address(proxy); - } - - /// @notice Deploy the L1CrossDomainMessengerProxy using a ResolvedDelegateProxy - function deployL1CrossDomainMessengerProxy() public broadcast returns (address addr_) { - IResolvedDelegateProxy proxy = IResolvedDelegateProxy( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "ResolvedDelegateProxy", - _nick: "L1CrossDomainMessengerProxy", - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IResolvedDelegateProxy.__constructor__, - (IAddressManager(mustGetAddress("AddressManager")), "OVM_L1CrossDomainMessenger") - ) - ) - }) - ); - addr_ = address(proxy); - } - /// @notice Deploys an ERC1967Proxy contract with the ProxyAdmin as the owner. /// @param _name The name of the proxy contract to be deployed. /// @return addr_ The address of the deployed proxy contract. @@ -696,95 +597,6 @@ contract Deploy is Deployer { addr_ = address(oracle); } - /// @notice Deploy Mips VM. Deploys either MIPS or MIPS64 depending on the environment - function deployMips() public broadcast returns (address addr_) { - addr_ = DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: Config.useMultithreadedCannon() ? "MIPS64" : "MIPS", - _args: DeployUtils.encodeConstructor( - abi.encodeCall(IMIPS2.__constructor__, (IPreimageOracle(mustGetAddress("PreimageOracle")))) - ) - }); - save("Mips", address(addr_)); - } - - /// @notice Deploy the AnchorStateRegistry - function deployAnchorStateRegistry() public broadcast returns (address addr_) { - IAnchorStateRegistry anchorStateRegistry = IAnchorStateRegistry( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "AnchorStateRegistry", - _args: DeployUtils.encodeConstructor( - abi.encodeCall( - IAnchorStateRegistry.__constructor__, - (IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"))) - ) - ) - }) - ); - - addr_ = address(anchorStateRegistry); - } - - /// @notice Deploy the L1StandardBridge - function deployL1StandardBridge() public broadcast returns (address addr_) { - IL1StandardBridge bridge = IL1StandardBridge( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "L1StandardBridge", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ())) - }) - ); - - // Override the `L1StandardBridge` contract to the deployed implementation. This is necessary - // to check the `L1StandardBridge` implementation alongside dependent contracts, which - // are always proxies. - Types.ContractSet memory contracts = _proxies(); - contracts.L1StandardBridge = address(bridge); - ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false }); - - addr_ = address(bridge); - } - - /// @notice Deploy the L1ERC721Bridge - function deployL1ERC721Bridge() public broadcast returns (address addr_) { - IL1ERC721Bridge bridge = IL1ERC721Bridge( - DeployUtils.create2AndSave({ - _save: this, - _salt: _implSalt(), - _name: "L1ERC721Bridge", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ())) - }) - ); - - // Override the `L1ERC721Bridge` contract to the deployed implementation. This is necessary - // to check the `L1ERC721Bridge` implementation alongside dependent contracts, which - // are always proxies. - Types.ContractSet memory contracts = _proxies(); - contracts.L1ERC721Bridge = address(bridge); - - ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false }); - - addr_ = address(bridge); - } - - /// @notice Transfer ownership of the address manager to the ProxyAdmin - function transferAddressManagerOwnership() public broadcast { - console.log("Transferring AddressManager ownership to IProxyAdmin"); - IAddressManager addressManager = IAddressManager(mustGetAddress("AddressManager")); - address owner = addressManager.owner(); - address proxyAdmin = mustGetAddress("ProxyAdmin"); - if (owner != proxyAdmin) { - addressManager.transferOwnership(proxyAdmin); - console.log("AddressManager ownership transferred to %s", proxyAdmin); - } - - require(addressManager.owner() == proxyAdmin); - } - /// @notice Deploy the DataAvailabilityChallenge function deployDataAvailabilityChallenge() public broadcast returns (address addr_) { IDataAvailabilityChallenge dac = IDataAvailabilityChallenge( @@ -1047,28 +859,6 @@ contract Deploy is Deployer { }); } - /// @notice Sets the implementation for the `PERMISSIONED_CANNON` game type in the `DisputeGameFactory` - function setPermissionedCannonFaultGameImplementation(bool _allowUpgrade) public broadcast { - console.log("Setting Cannon PermissionedDisputeGame implementation"); - IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); - IDelayedWETH weth = IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); - - // Deploys and sets the Permissioned FaultDisputeGame implementation in the factory. - _setFaultGameImplementation({ - _factory: factory, - _allowUpgrade: _allowUpgrade, - _params: FaultDisputeGameParams({ - anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - weth: weth, - gameType: GameTypes.PERMISSIONED_CANNON, - absolutePrestate: loadMipsAbsolutePrestate(), - faultVm: IBigStepper(mustGetAddress("Mips")), - maxGameDepth: cfg.faultGameMaxDepth(), - maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())) - }) - }); - } - /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory` function setAlphabetFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { console.log("Setting Alphabet FaultDisputeGame implementation"); @@ -1272,6 +1062,7 @@ contract Deploy is Deployer { }); } + /// @notice Reset the initialized value on a proxy contract so that it can be initialized again function resetInitializedProxy(string memory _contractName) internal { console.log("resetting initialized value on %s Proxy", _contractName); address proxy = mustGetAddress(string.concat(_contractName, "Proxy")); From 2b589dfd0bfe371f99dcab24f21ff9dd60938561 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Mon, 25 Nov 2024 17:21:12 -0500 Subject: [PATCH 28/61] maint: clean src imports (#13056) Cleans up import statments in all contracts within the src/ directory. We should probably add a semgrep rule or a check that confirms that everything looks good. I'll leave that part for another commit. --- .../snapshots/semver-lock.json | 126 +++++++++--------- .../src/L1/OPContractsManager.sol | 11 +- .../src/L1/OPContractsManagerInterop.sol | 3 + .../src/L1/OptimismPortalInterop.sol | 10 +- .../src/L1/ProtocolVersions.sol | 11 +- .../src/L1/SuperchainConfig.sol | 11 +- .../src/L1/SystemConfigInterop.sol | 8 +- .../L1/interfaces/IOptimismPortalInterop.sol | 2 +- .../contracts-bedrock/src/L2/BaseFeeVault.sol | 10 +- .../src/L2/CrossDomainOwnable.sol | 3 + .../contracts-bedrock/src/L2/CrossL2Inbox.sol | 9 +- packages/contracts-bedrock/src/L2/L1Block.sol | 9 +- .../src/L2/L1BlockInterop.sol | 4 +- .../contracts-bedrock/src/L2/L1FeeVault.sol | 10 +- .../src/L2/L2StandardBridge.sol | 6 +- .../src/L2/L2StandardBridgeInterop.sol | 4 +- .../src/L2/L2ToL1MessagePasser.sol | 7 +- .../src/L2/L2ToL2CrossDomainMessenger.sol | 13 +- .../src/L2/OptimismSuperchainERC20.sol | 15 ++- .../src/L2/OptimismSuperchainERC20Beacon.sol | 9 +- .../src/L2/OptimismSuperchainERC20Factory.sol | 15 ++- .../src/L2/SequencerFeeVault.sol | 10 +- .../src/L2/SuperchainERC20.sol | 17 ++- .../contracts-bedrock/src/asterisc/RISCV.sol | 5 +- .../contracts-bedrock/src/cannon/MIPS.sol | 11 +- .../contracts-bedrock/src/cannon/MIPS2.sol | 11 +- .../contracts-bedrock/src/cannon/MIPS64.sol | 11 +- .../cannon/libraries/MIPS64Instructions.sol | 1 + .../src/cannon/libraries/MIPS64Memory.sol | 1 + .../src/cannon/libraries/MIPS64State.sol | 1 + .../src/cannon/libraries/MIPS64Syscalls.sol | 1 + .../src/cannon/libraries/MIPSInstructions.sol | 1 + .../src/cannon/libraries/MIPSMemory.sol | 1 + .../src/cannon/libraries/MIPSState.sol | 1 + .../src/cannon/libraries/MIPSSyscalls.sol | 1 + .../src/dispute/lib/Errors.sol | 1 + .../src/dispute/lib/LibUDT.sol | 1 + .../src/dispute/lib/Types.sol | 1 + .../src/governance/GovernanceToken.sol | 1 + .../src/legacy/AddressManager.sol | 1 + .../src/legacy/DeployerWhitelist.sol | 5 +- .../src/legacy/L1ChugSplashProxy.sol | 3 + .../src/legacy/LegacyMessagePasser.sol | 5 +- .../src/legacy/LegacyMintableERC20.sol | 3 + .../src/legacy/ResolvedDelegateProxy.sol | 1 + .../src/libraries/Arithmetic.sol | 1 + .../src/libraries/Constants.sol | 1 + .../src/libraries/Encoding.sol | 1 + .../src/libraries/GasPayingToken.sol | 3 +- .../src/libraries/Hashing.sol | 1 + .../src/libraries/rlp/RLPReader.sol | 3 +- .../src/libraries/trie/MerkleTrie.sol | 5 +- .../src/libraries/trie/SecureMerkleTrie.sol | 3 +- .../src/periphery/AssetReceiver.sol | 3 +- .../src/periphery/Transactor.sol | 1 + .../src/periphery/TransferOnion.sol | 3 + .../src/periphery/drippie/Drippie.sol | 7 +- .../drippie/dripchecks/CheckBalanceLow.sol | 3 +- .../drippie/dripchecks/CheckGelatoLow.sol | 3 +- .../drippie/dripchecks/CheckSecrets.sol | 3 +- .../drippie/dripchecks/CheckTrue.sol | 3 +- .../src/periphery/faucet/Faucet.sol | 9 +- .../authmodules/AdminFaucetAuthModule.sol | 7 +- .../faucet/authmodules/IFaucetAuthModule.sol | 3 +- .../src/safe/LivenessGuard.sol | 13 +- .../src/safe/LivenessModule.sol | 9 +- .../src/universal/CrossDomainMessenger.sol | 1 + .../src/universal/ERC721Bridge.sol | 9 +- .../src/universal/OptimismMintableERC20.sol | 13 +- .../OptimismMintableERC20Factory.sol | 9 +- .../src/universal/OptimismMintableERC721.sol | 11 +- .../OptimismMintableERC721Factory.sol | 7 +- .../contracts-bedrock/src/universal/Proxy.sol | 1 + .../src/universal/StandardBridge.sol | 18 ++- .../src/universal/StorageSetter.sol | 9 +- .../vendor/eas/resolver/ISchemaResolver.sol | 2 +- .../test/L1/OptimismPortalInterop.t.sol | 14 +- .../test/L1/SystemConfigInterop.t.sol | 2 +- .../test/L2/L1BlockInterop.t.sol | 14 +- .../test/L2/L2ToL2CrossDomainMessenger.t.sol | 22 +-- .../test/legacy/L1BlockNumber.t.sol | 12 +- 81 files changed, 389 insertions(+), 231 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 444f4522c65..c387881a61f 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,8 +20,8 @@ "sourceCodeHash": "0x4132ff37d267cb12224b75ea806c0aa7d25407b0d66ce526d7fcda8f7d223882" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0xd038cc35325d023499151264232d75fa4ecc81f04a8c8353e6b50c43af224d6e", - "sourceCodeHash": "0xa13f3ab2b8744015290dbabe5f20fdd44774607e6a7ad3e5e016303fc4aa8c12" + "initCodeHash": "0xdc41db13327e1f51ce996c088538c227a82c37d62906eca1aa456d71fa605ff3", + "sourceCodeHash": "0x08aca8a70f42a0556f0fc7b1cd4d4aaf152215ab246c132e23074558497fe03b" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0x152167cfa18635ae4918a6eb3371a599cfa084418c0a652799cdb48bfc0ee0cc", @@ -32,32 +32,32 @@ "sourceCodeHash": "0x66ac1212760db53a2bb1839e4cd17dc071d9273b8e6fb80646b79e91b3371c1a" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x39f66ac74341ec235fbdd0d79546283210bd8ac35a2ab2c4bd36c9722ce18411", - "sourceCodeHash": "0xbb98144285b9530e336f957d10b20363b350876597e30fd34821940896a2bae8" + "initCodeHash": "0x902ce448a29a72805cd74b7fc62519fa3d12338851b518b7d01e8a40ba232c72", + "sourceCodeHash": "0x8de1b2d4675624a2a3aee135ad8780a07ca91002a5952f2b6501fdf20c92b753" }, "src/L1/ProtocolVersions.sol": { - "initCodeHash": "0xefd4806e8737716d5d2022ca2e9e9fba0a0cb5714b026166b58e472222c7d15f", - "sourceCodeHash": "0x15205131bf420aa6d03c558bb75dd49cd7439caed7ccdcbfd89c4170a48c94f5" + "initCodeHash": "0x98dc9a7ecd1919a8cf4bcca4fb28b112641b2aa5132fb5467a349fb80974957a", + "sourceCodeHash": "0x9b953cdbc049492d20a15d48a9081977a91f8e7c72eee3792d86871e70b1a40a" }, "src/L1/SuperchainConfig.sol": { - "initCodeHash": "0xfca12d9016c746e5c275b186e0ca40cfd65cf45a5665aab7589a669fea3abb47", - "sourceCodeHash": "0x39489a85bc3a5c8560f82d41b31bf7fe22f5b648f4ed538f61695a73092ea9eb" + "initCodeHash": "0xebe9a9dbf6df5288fae3634a9d71ce12bd8acb461086de28a2fb4239097dcf80", + "sourceCodeHash": "0xd931c19a85a070119f5b670d1f4dc90512847b408aa4ee29c98231257cf0c77c" }, "src/L1/SystemConfig.sol": { "initCodeHash": "0x0eda38e2fb2687a324289f04ec8ad0d2afe51f45219d074740fb4a0e24ea6569", "sourceCodeHash": "0x6dbbe8716ca8cd2fba3da8dcae0ca0c4b1f3e9dd04220fb24a15666b23300927" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x443fd84f8dbc38f03e59a56b99099b5e4b28de3e860a5d16c1a21101745622a4", - "sourceCodeHash": "0x5c2e00cd8939a538eb38580d76e70d27dd1e8e6cd9328e1978468981017736e6" + "initCodeHash": "0x845af4e83836221a014f46544fe2a29c66706513b7eed39c59f0505d2662731a", + "sourceCodeHash": "0x8df468eb79cf68ee38bada32e7d7c87449c129f1955d464fa774977c770715c7" }, "src/L2/BaseFeeVault.sol": { - "initCodeHash": "0xbf49824cf37e201181484a8a423fcad8f504dc925921a2b28e83398197858dec", - "sourceCodeHash": "0x983e8e248c61e362ba6a01dd2e217a535c9bb828dc0b4421f5f27e0577f2e14c" + "initCodeHash": "0xc23d0437deb5c2e9f8831b9325c77e9d07467c9286f81c0ef47cfef4e242f96b", + "sourceCodeHash": "0x2f3f64d4307a081311222b34afa76e587aca3789367f6ea77bc1bfb6d9b39563" }, "src/L2/CrossL2Inbox.sol": { - "initCodeHash": "0x31ecaebf368ab3333e80c6dc004b3c9f9a31f813c3138ab388bb3eead9f1b4ee", - "sourceCodeHash": "0xa1779d84a14332dcdd167293171d0fe2629d759a23d7cc34ffe2bde7e1605dbc" + "initCodeHash": "0x753a7685c4ab405b71a19a7f8aa20a2517b4943bee5d5e616a6fccd8f0531993", + "sourceCodeHash": "0xc74277f9502338def330444413ff77157e200110cd7f57cd9a18f9ffe4a18a6c" }, "src/L2/ETHLiquidity.sol": { "initCodeHash": "0x713c18f95a6a746d0703f475f3ae10c106c9b9ecb64d881a2e61b8969b581371", @@ -68,16 +68,16 @@ "sourceCodeHash": "0xa12ce15ded3cca681b2fc9facaebbb45d740dd6f9c9496333c1c46689c9a2d99" }, "src/L2/L1Block.sol": { - "initCodeHash": "0xa919d2aa76a7ecdfd076e2b1dbece499cc85706075f16eb6fa7b1a0fa7b38c1b", - "sourceCodeHash": "0x692cfcbc06dba6328f6e5c6b500741df04e4bdf730b2069aeb5d168355ea7b6f" + "initCodeHash": "0xb25ff86c5b199f0e4db9f814f3d107cd929278a39e838c541af79d49d472b646", + "sourceCodeHash": "0xa44964dc0178949b83fc4100c03933c6d6f66e9654ce6b4aff5847a889a189d4" }, "src/L2/L1BlockInterop.sol": { - "initCodeHash": "0x62e9cc59daaf72066ac20597a666db33e9a7b3f7be71a3d47ea4841a9aca9d07", - "sourceCodeHash": "0xe57627347366d74029a0d24f0b45d7b9cf82b81c94681d0f633d5e5c37c8de4a" + "initCodeHash": "0xb59a6a62926084b9979e337183ee54b4c4e9ceeda7e39bd70bd7b4228464d2e0", + "sourceCodeHash": "0x5681bb385bf1685cb204a612ef8a891e91763e699c7738a3a97b171852d585b5" }, "src/L2/L1FeeVault.sol": { - "initCodeHash": "0xbf49824cf37e201181484a8a423fcad8f504dc925921a2b28e83398197858dec", - "sourceCodeHash": "0xc7cda130f2bb3648e04d5a480082aa1789e16456c1280954d822b05d30100b2d" + "initCodeHash": "0xc23d0437deb5c2e9f8831b9325c77e9d07467c9286f81c0ef47cfef4e242f96b", + "sourceCodeHash": "0x3f0acc4427d6f72debe4393c746b759c7c736f28b8c4f42391de622c9be3bcb3" }, "src/L2/L2CrossDomainMessenger.sol": { "initCodeHash": "0xc496495496b96ea0eaf417c5e56b295836c12db3e6aafe2e607563e7a50b5b65", @@ -88,40 +88,40 @@ "sourceCodeHash": "0xf8569c75b801f38f8a5a41e94e90f159ddc5f5412804b26e3e564755a50631b8" }, "src/L2/L2StandardBridge.sol": { - "initCodeHash": "0xcb4aa19f0cd43a35cb5c65f26c3cfd7c41f1d1e5bcc15aef6096d385df7272c9", - "sourceCodeHash": "0x89771b53b7f6e64d943afb2a4bf15395efcf20d5302b76a18e52fa7cce8cdc56" + "initCodeHash": "0x959ce0daeb14884127cff4d701b294fb29b5d7c2d890ec4fdf704c451164811e", + "sourceCodeHash": "0xd5f91687a178254714203c702afe0c2343c45c4684b914aa873dcb641e73e725" }, "src/L2/L2StandardBridgeInterop.sol": { - "initCodeHash": "0xc4eaece28d2cfca3c51247c3cce320a167a83c7fd13aea5736549d2b25e0b139", - "sourceCodeHash": "0x9e80044adf5f83c30b520ee153b75be5a152081c9e1271e7e618ecfccd1fb4ac" + "initCodeHash": "0x745f5e3a0deb6cd8fa5a339c83cc91f9ce63de570a7ed23e2da645bebaa79494", + "sourceCodeHash": "0x0ca6d8900a02c213acca44c8cb56df816fa1bebd6903a9ea6d4c21525c936c12" }, "src/L2/L2ToL1MessagePasser.sol": { - "initCodeHash": "0x13fe3729beb9ed966c97bef09acb9fe5043fe651d453145073d05f2567fa988d", - "sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c" + "initCodeHash": "0xe65929ad618380e7f005f042a0a9c8e662ad10d6e1c53bfb7f518a54b848fd79", + "sourceCodeHash": "0xd61a1face234756e99b7ab8383eef40e62833a91f727a77997d6f0e384526637" }, "src/L2/L2ToL2CrossDomainMessenger.sol": { - "initCodeHash": "0xc1c80c662aafebb639f62f17d9fefd6954947fd43dc31c278950727491471a94", - "sourceCodeHash": "0xac12ab96ffe91c75bfe74768271a725e1cbe3996b16284171440dd71bcc215b6" + "initCodeHash": "0x085c83fd07ce54b9d007e548008dd9d4c31d19cae9b9ca3aa1496191f84499fa", + "sourceCodeHash": "0x20d6a4f42b3169c17f938cfe479de7bd558c6ded816e1fcfddcdc5d86583b42b" }, "src/L2/OptimismSuperchainERC20.sol": { - "initCodeHash": "0x22fed5371ad9b4c2711ce5cbee889d332887aa5f5ff6b37e36c31acefe3bbeee", - "sourceCodeHash": "0xf68baaee0a09ea51d5a4e821df79976c0914369ebc8e5fd27bbbf89072254fc8" + "initCodeHash": "0x0e76b7ffa8af16f1bc5f74a55eb3ed64016228032b67c5f45afa7fd6fe4acf7e", + "sourceCodeHash": "0x92f370d0e167b7cec0deaded71d9c4a5a8303a2b921320123d3c32eeca1cc100" }, "src/L2/OptimismSuperchainERC20Beacon.sol": { - "initCodeHash": "0x23dba3ceb9e58646695c306996c9e15251ac79acc6339c1a93d10a4c79da6dab", - "sourceCodeHash": "0xf4379e49665823c877f5732f35068435ce06e2394fce6910a5e113d16cdc9f95" + "initCodeHash": "0xb032e99f5c205c8b474da89887e350277cdd05b99ee28374b97bfae18ef7a72c", + "sourceCodeHash": "0xc9ec1a022f82a3b463fad11d2cd6ade74bb0801ae797fdc0494840587fc595dd" }, "src/L2/OptimismSuperchainERC20Factory.sol": { - "initCodeHash": "0x18a362c57f08b611db98dfde96121385e938f995c84e3547c1c03fd49f9db2fd", - "sourceCodeHash": "0x450cd89d0aae7bbc85ff57a14a6d3468c24c6743f25943f6d895d34b1456c456" + "initCodeHash": "0xe6a098346699c3df248050fc3301197661d391f8e4849a93f00afeac17cae317", + "sourceCodeHash": "0x51980d07914ae48fd632aa54df24f3d6e2d335d0223a1d2ddd4ca5ced1797c16" }, "src/L2/SequencerFeeVault.sol": { - "initCodeHash": "0xcaadbf08057b5d47f7704257e9385a29e42a7a08c818646d109c5952d3d35218", - "sourceCodeHash": "0x05bbc6039e5a9ff38987e7b9b89c69e2ee8aa4b7ca20dd002ea1bbd3d70f27f3" + "initCodeHash": "0xf05acc7dcb80474e48ea36a3511bd4cbb35da065ed6280918b87a47c13a22cfc", + "sourceCodeHash": "0x3c0d09bd700b9db218445ecce76006574cabfe8c40c2156a6787c8a1360d7835" }, "src/L2/SuperchainERC20.sol": { "initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "sourceCodeHash": "0x77adb9ea7a9e9cf3dc5943607dcacacf7a703bd110d2a5627e7075b766aae29f" + "sourceCodeHash": "0x4c40f0249c1c9871efd2e957dd9c769cc52b88d896385dd4d547f82eb06284be" }, "src/L2/SuperchainTokenBridge.sol": { "initCodeHash": "0x1cd2afdae6dd1b6ebc17f1d529e7d74c9b8b21b02db8589b8e389e2d5523d775", @@ -136,20 +136,20 @@ "sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b" }, "src/asterisc/RISCV.sol": { - "initCodeHash": "0x6b4323061187f2c8efe8de43bf1ecdc0798e2d95ad69470ed4151dadc094fedf", - "sourceCodeHash": "0xd824f1ead87a1214fa8a4b435f493a80b7340ec2c959d2c1e1e9e8c062a42c4a" + "initCodeHash": "0x8d47aa0b81d7fe6bd0aeac18f26d7c0b285f58740bb9d92dac0ddf706c85309f", + "sourceCodeHash": "0xaebcda0a16da65fc7833672073ea6872c40d1ba722f0a6515c4a293e380f96c6" }, "src/cannon/MIPS.sol": { - "initCodeHash": "0xa3cbf121bad13c00227ea4fef128853d9a86b7ec9158de894f99b58d38d7630a", - "sourceCodeHash": "0xd8467700c80b3e62fa37193dc6513bac35282094b686b50e162e157f704dde00" + "initCodeHash": "0xb4aec227019dacd6194d6aeb9ca68c23c60b95618d18a4ebc09243514aeb1f05", + "sourceCodeHash": "0x4d43b3f2918486aa76d2d59ac42e4f6aa2f58538c7e95a5cb99b63c9588b5f1c" }, "src/cannon/MIPS2.sol": { - "initCodeHash": "0xc38c76ab3aad78c81ca01b3235b402614972d6604b22fda1e870f1bf47be1194", - "sourceCodeHash": "0x3d38b1924669d1bde756f1306601c764a6d31f428ac72667a3dd194b3388210d" + "initCodeHash": "0xe3879b5772820d837bc1c77c32a1200eb26cf901d9302dff9f0e9759331e380e", + "sourceCodeHash": "0x1c45a8f4c8c9ded7043d63965cb114d17f801c6cd4d8233cb16838c5f9a02675" }, "src/cannon/MIPS64.sol": { - "initCodeHash": "0x93aa8d7f9fd3c22276c0d303a3fefdf8f73cc55807b35e483bba64c92d02aaef", - "sourceCodeHash": "0x171d66c651fdad2ac9c287da92689815a5b09589945ada092179508ad2326306" + "initCodeHash": "0xa4a761f480a26ec1926c5a8b4831440211c0441bd41d503b0aad189e030d35dc", + "sourceCodeHash": "0x7ddcf8584f9bd92abd1eb45bc198f5b0ec54acaf292f60e919d674cc56fb8abc" }, "src/cannon/PreimageOracle.sol": { "initCodeHash": "0x5d7e8ae64f802bd9d760e3d52c0a620bd02405dc2c8795818db9183792ffe81c", @@ -172,48 +172,48 @@ "sourceCodeHash": "0x730eff9147294c115a0a53e7e75771bcc4a517beb48457140ab929a8d1510893" }, "src/legacy/DeployerWhitelist.sol": { - "initCodeHash": "0x0b8177ed75b69eddbb9ce6537683f69a9935efed86a1d6faa8feaafbd151c1bd", - "sourceCodeHash": "0xc8fe9571fcf8fcb51a4dcb00ffa97f43a9ce811c323c4926e710b28c90a9005f" + "initCodeHash": "0xf232863fde5cd65368bcb4a79b41b5a4a09c59ede5070f82fd3f13f681bea7d8", + "sourceCodeHash": "0xd8d65492470907907d75574c1260fb349903af22c89098ea091439fc809310a9" }, "src/legacy/L1BlockNumber.sol": { "initCodeHash": "0x542955f1a84b304eaf291f76633b03e4c87c2654f7eff46c3bea94d27346ea1f", "sourceCodeHash": "0x898c239e6367a0971a075df18030a033cdada26983fa8a5cd6e7b88ec90d4958" }, "src/legacy/LegacyMessagePasser.sol": { - "initCodeHash": "0xefc6ed9e325c2d614ea0d28c3eabfff1b345f7c6054e90253c6a091c29508267", - "sourceCodeHash": "0xaa08a61448f485b277af57251d2089cc6a80ce0a763bf7184d48ffed5034ef69" + "initCodeHash": "0x11802672c929c4e92faeb7bee66617574b249b60a210f11ce29a5caa0e3d6bac", + "sourceCodeHash": "0x851ab8a2cd40798fce25698d4cfdb9dbf9c4c1e53f3cc8d1a325a6dd368807b0" }, "src/safe/DeputyGuardianModule.sol": { "initCodeHash": "0xd95e562f395d4eb6e332f4474dffab660ada9e9da7c79f58fb6052278e0904df", "sourceCodeHash": "0x45daabe094de0287e244e6fea4f1887b9adc09b07c47dc77361b1678645a1470" }, "src/safe/LivenessGuard.sol": { - "initCodeHash": "0x9ac0b039b1591f7c00cf11cb758d118c9b42e6e08250b619d6b6fd605a43d5ee", - "sourceCodeHash": "0xc1a968b0c6fbc4d82c2821c917b273feaaa224d258886b394416e84ee250d026" + "initCodeHash": "0xd449cef5d62dea387f5c4fd18382f5427532c443d29b3dcf0f645dbb6756ccb4", + "sourceCodeHash": "0x745f72d907d9a8e95b5fdfe9fd9a910456f2417c42b81b0a3a764c20c13d7ed7" }, "src/safe/LivenessModule.sol": { - "initCodeHash": "0xcfccdd9e423c95a0ddc6e09ccb6333d5fc8429ed2b8fc872f1290d392ae13aad", - "sourceCodeHash": "0xd1479c60087f352385b6d5379ef3cc07839f671d617626b4c94ece91da781ef2" + "initCodeHash": "0xb16fd6cdfe5125dbb065ab1b6fcd7a58665e9fc4907b1089c8a496576be5d4f7", + "sourceCodeHash": "0x17e70b1d4ffc876fde920eaeb5874ff8a39dfa03b1e24044dc73aff2820db1ef" }, "src/universal/OptimismMintableERC20.sol": { - "initCodeHash": "0x9cd677275b175812f1d5f90a127dbf7b3592714fd842a7a0de3988d716ca3eac", - "sourceCodeHash": "0x5611d8082f68af566554d7f09640b4b1f0e3efee4da1372b68fc7fc538a35ac7" + "initCodeHash": "0xc97c9502af8e83f1d9bd81f711c3d73db298dfdba465f463b3faa43a8208ed47", + "sourceCodeHash": "0x7e7ada21d7e5fb92521dad343ff71da9bdabd6e04882c81b8c8f74854f755ba6" }, "src/universal/OptimismMintableERC20Factory.sol": { - "initCodeHash": "0x03ad07bd7f89a29f1850fa8b5d377daf0e1d5aef6cb458a127df520549e8e8e6", - "sourceCodeHash": "0xdb6ec93782a4a217475195507740794a4f5553b9032e7ba31dc48b81f579a940" + "initCodeHash": "0x4ba75c8864565ac14aa213d2aacda58ce0f82b197fa72393328ac6968edb54fb", + "sourceCodeHash": "0xcd09be31be4e0fda6d329bd6ac6dccded3f029514be4908860db4d757ebb7bc7" }, "src/universal/OptimismMintableERC721.sol": { - "initCodeHash": "0x8aa309f2676d5267b6c9e411f88dc6e4badce414b8d66b330df3f60e9836380e", - "sourceCodeHash": "0x03bf7ad4d2b751bdead9930fc8f89b8e55d40dd4b2f5670fd339e87ae81f8b49" + "initCodeHash": "0xc7c5dbc9d19314f8ad00bd867a9186d04e7471502671c3daa23d90c1e3e16320", + "sourceCodeHash": "0x089ee309a0d9061646ab7a2781f80e5d94a74cc38fe808a3696e3984683d0a89" }, "src/universal/OptimismMintableERC721Factory.sol": { - "initCodeHash": "0x5ea977ba35558c3b75bebe28900548c763d205e40d6cf7660292b8e96bf3aea8", - "sourceCodeHash": "0x063ca3a0a2e3c592173af6157e383b5aaeff752000f98648a5c71260bb26590a" + "initCodeHash": "0xf62b7daa5e5005d989d9afb177c314868bef48641a7069ddf1d6c6656e064929", + "sourceCodeHash": "0x2ea30e241a348bfdd3dae41375b8a5db8c6eb609650f49a0945e6d453b5b6a41" }, "src/universal/StorageSetter.sol": { - "initCodeHash": "0x21b3059e9b13b330f76d02b61f61dcfa3abf3517a0b56afa0895c4b8291740bf", - "sourceCodeHash": "0xc1ea12a87e3a7ef9c950f0a41a4e35b60d4d9c4c816ff671dbfca663861c16f4" + "initCodeHash": "0x049f3c86965e575a370b14f7f49f3f15436ffb5ee1059615bb708659d7aae7de", + "sourceCodeHash": "0x5dc6b0b4ae4ab29085c52f74a4498d8a3d04928b844491749cd7186623e8b967" }, "src/vendor/eas/EAS.sol": { "initCodeHash": "0xf96d1ebc530ed95e2dffebcfa2b4a1f18103235e6352d97838b77b7a2c14567b", diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index a2a5a5f215b..c0978e66cad 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { Blueprint } from "src/libraries/Blueprint.sol"; import { Constants } from "src/libraries/Constants.sol"; +import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol"; +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; @@ -11,16 +14,12 @@ import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; - import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol"; - import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; -import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol"; - import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; @@ -115,8 +114,8 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 1.0.0-beta.21 - string public constant version = "1.0.0-beta.21"; + /// @custom:semver 1.0.0-beta.22 + string public constant version = "1.0.0-beta.22"; /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol index 79e0efda973..3366087bd87 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OPContractsManager } from "src/L1/OPContractsManager.sol"; + +// Interfaces import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 4c238c415d3..abad969dffa 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -3,13 +3,15 @@ pragma solidity 0.8.15; // Contracts import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Unauthorized } from "src/libraries/PortalErrors.sol"; +// Interfaces +import { IL1BlockInterop, ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; + /// @custom:proxied true /// @title OptimismPortalInterop /// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 @@ -23,9 +25,9 @@ contract OptimismPortalInterop is OptimismPortal2 { OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds) { } - /// @custom:semver +interop-beta.2 + /// @custom:semver +interop-beta.3 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.2"); + return string.concat(super.version(), "+interop-beta.3"); } /// @notice Sets static configuration options for the L2 system. @@ -48,7 +50,7 @@ contract OptimismPortalInterop is OptimismPortal2 { uint256(0), // value uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit false, // isCreation, - abi.encodeCall(L1BlockInterop.setConfig, (_type, _value)) + abi.encodeCall(IL1BlockInterop.setConfig, (_type, _value)) ) ); } diff --git a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol index 8d4982ecea0..83fe4a90b63 100644 --- a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol +++ b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +// Libraries import { Storage } from "src/libraries/Storage.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @notice ProtocolVersion is a numeric identifier of the protocol version. type ProtocolVersion is uint256; @@ -36,8 +41,8 @@ contract ProtocolVersions is OwnableUpgradeable, ISemver { event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 1.0.1-beta.3 - string public constant version = "1.0.1-beta.3"; + /// @custom:semver 1.0.1-beta.4 + string public constant version = "1.0.1-beta.4"; /// @notice Constructs the ProtocolVersion contract. Cannot set /// the owner to `address(0)` due to the Ownable contract's diff --git a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol index 51b13936c81..5cac41ece63 100644 --- a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol +++ b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +// Libraries import { Storage } from "src/libraries/Storage.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @custom:proxied true /// @custom:audit none This contracts is not yet audited. /// @title SuperchainConfig @@ -36,8 +41,8 @@ contract SuperchainConfig is Initializable, ISemver { event ConfigUpdate(UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 1.1.1-beta.1 - string public constant version = "1.1.1-beta.1"; + /// @custom:semver 1.1.1-beta.2 + string public constant version = "1.1.1-beta.2"; /// @notice Constructs the SuperchainConfig contract. constructor() { diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol index 9e9503fe623..1bdc8ddc586 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol @@ -3,9 +3,7 @@ pragma solidity 0.8.15; // Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { IOptimismPortalInterop as IOptimismPortal } from "src/L1/interfaces/IOptimismPortalInterop.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { ConfigType } from "src/L2/L1BlockInterop.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; @@ -14,7 +12,9 @@ import { StaticConfig } from "src/libraries/StaticConfig.sol"; import { Storage } from "src/libraries/Storage.sol"; // Interfaces +import { IOptimismPortalInterop as IOptimismPortal } from "src/L1/interfaces/IOptimismPortalInterop.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; /// @custom:proxied true /// @title SystemConfigInterop @@ -68,9 +68,9 @@ contract SystemConfigInterop is SystemConfig { Storage.setAddress(DEPENDENCY_MANAGER_SLOT, _dependencyManager); } - /// @custom:semver +interop-beta.4 + /// @custom:semver +interop-beta.5 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.4"); + return string.concat(super.version(), "+interop-beta.5"); } /// @notice Internal setter for the gas paying token address, includes validation. diff --git a/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol index 521c7232e12..5e8acc45c8c 100644 --- a/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol @@ -7,7 +7,7 @@ import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; -import { ConfigType } from "src/L2/L1BlockInterop.sol"; +import { ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; interface IOptimismPortalInterop { error AlreadyFinalized(); diff --git a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol index 2fd33b9290b..4dd6a87023b 100644 --- a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol @@ -1,19 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; +// Contracts import { FeeVault } from "src/L2/FeeVault.sol"; +// Libraries import { Types } from "src/libraries/Types.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000019 /// @title BaseFeeVault /// @notice The BaseFeeVault accumulates the base fee that is paid by transactions. contract BaseFeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.3 - string public constant version = "1.5.0-beta.3"; + /// @custom:semver 1.5.0-beta.4 + string public constant version = "1.5.0-beta.4"; /// @notice Constructs the BaseFeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/CrossDomainOwnable.sol b/packages/contracts-bedrock/src/L2/CrossDomainOwnable.sol index 3b532f58900..658cfc50f8b 100644 --- a/packages/contracts-bedrock/src/L2/CrossDomainOwnable.sol +++ b/packages/contracts-bedrock/src/L2/CrossDomainOwnable.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Contracts import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +// Libraries import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; /// @title CrossDomainOwnable diff --git a/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol b/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol index b330dfb0ceb..ca9129f710a 100644 --- a/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol +++ b/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { TransientContext, TransientReentrancyAware } from "src/libraries/TransientContext.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IDependencySet } from "src/L2/interfaces/IDependencySet.sol"; import { IL1BlockInterop } from "src/L2/interfaces/IL1BlockInterop.sol"; @@ -73,8 +76,8 @@ contract CrossL2Inbox is ISemver, TransientReentrancyAware { address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.9 - string public constant version = "1.0.0-beta.9"; + /// @custom:semver 1.0.0-beta.10 + string public constant version = "1.0.0-beta.10"; /// @notice Emitted when a cross chain message is being executed. /// @param msgHash Hash of message payload being executed. diff --git a/packages/contracts-bedrock/src/L2/L1Block.sol b/packages/contracts-bedrock/src/L2/L1Block.sol index 0b2ffd2c578..1f7a935339a 100644 --- a/packages/contracts-bedrock/src/L2/L1Block.sol +++ b/packages/contracts-bedrock/src/L2/L1Block.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; +// Libraries import { Constants } from "src/libraries/Constants.sol"; import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol"; import { NotDepositor } from "src/libraries/L1BlockErrors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000015 /// @title L1Block @@ -57,9 +60,9 @@ contract L1Block is ISemver, IGasToken { /// @notice The latest L1 blob base fee. uint256 public blobBaseFee; - /// @custom:semver 1.5.1-beta.3 + /// @custom:semver 1.5.1-beta.4 function version() public pure virtual returns (string memory) { - return "1.5.1-beta.3"; + return "1.5.1-beta.4"; } /// @notice Returns the gas paying token, its decimals, name and symbol. diff --git a/packages/contracts-bedrock/src/L2/L1BlockInterop.sol b/packages/contracts-bedrock/src/L2/L1BlockInterop.sol index 2cf6bd96c7d..b3a5cf51be1 100644 --- a/packages/contracts-bedrock/src/L2/L1BlockInterop.sol +++ b/packages/contracts-bedrock/src/L2/L1BlockInterop.sol @@ -49,9 +49,9 @@ contract L1BlockInterop is L1Block { /// keccak256(abi.encode(uint256(keccak256("l1Block.identifier.isDeposit")) - 1)) & ~bytes32(uint256(0xff)) uint256 internal constant IS_DEPOSIT_SLOT = 0x921bd3a089295c6e5540e8fba8195448d253efd6f2e3e495b499b627dc36a300; - /// @custom:semver +interop-beta.1 + /// @custom:semver +interop-beta.2 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.1"); + return string.concat(super.version(), "+interop-beta.2"); } /// @notice Returns whether the call was triggered from a a deposit or not. diff --git a/packages/contracts-bedrock/src/L2/L1FeeVault.sol b/packages/contracts-bedrock/src/L2/L1FeeVault.sol index c80c40b9849..3e69806ce53 100644 --- a/packages/contracts-bedrock/src/L2/L1FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/L1FeeVault.sol @@ -1,19 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; +// Contracts import { FeeVault } from "src/L2/FeeVault.sol"; +// Libraries import { Types } from "src/libraries/Types.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @custom:proxied true /// @custom:predeploy 0x420000000000000000000000000000000000001A /// @title L1FeeVault /// @notice The L1FeeVault accumulates the L1 portion of the transaction fees. contract L1FeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.3 - string public constant version = "1.5.0-beta.3"; + /// @custom:semver 1.5.0-beta.4 + string public constant version = "1.5.0-beta.4"; /// @notice Constructs the L1FeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol index 63bda3209fb..d2cb6f81556 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.15; // Contracts import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; @@ -11,6 +10,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; /// @custom:proxied true @@ -58,9 +58,9 @@ contract L2StandardBridge is StandardBridge, ISemver { ); /// @notice Semantic version. - /// @custom:semver 1.11.1-beta.3 + /// @custom:semver 1.11.1-beta.4 function version() public pure virtual returns (string memory) { - return "1.11.1-beta.3"; + return "1.11.1-beta.4"; } /// @notice Constructs the L2StandardBridge contract. diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol b/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol index e17ef29dd96..622d9218723 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol @@ -40,9 +40,9 @@ contract L2StandardBridgeInterop is L2StandardBridge { event Converted(address indexed from, address indexed to, address indexed caller, uint256 amount); /// @notice Semantic version. - /// @custom:semver +interop-beta.2 + /// @custom:semver +interop-beta.3 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.2"); + return string.concat(super.version(), "+interop-beta.3"); } /// @notice Converts `amount` of `from` token to `to` token. diff --git a/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol b/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol index 94b8213983e..9492b3fada1 100644 --- a/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol +++ b/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Burn } from "src/libraries/Burn.sol"; + +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @custom:proxied true @@ -48,8 +51,8 @@ contract L2ToL1MessagePasser is ISemver { /// @param amount Amount of ETh that was burned. event WithdrawerBalanceBurnt(uint256 indexed amount); - /// @custom:semver 1.1.1-beta.1 - string public constant version = "1.1.1-beta.1"; + /// @custom:semver 1.1.1-beta.2 + string public constant version = "1.1.1-beta.2"; /// @notice Allows users to withdraw ETH by sending directly to this contract. receive() external payable { diff --git a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol index bf53133484d..731d36c9787 100644 --- a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; +// Libraries import { Encoding } from "src/libraries/Encoding.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { CrossL2Inbox, Identifier } from "src/L2/CrossL2Inbox.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; import { TransientReentrancyAware } from "src/libraries/TransientContext.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IDependencySet } from "src/L2/interfaces/IDependencySet.sol"; +import { ICrossL2Inbox, Identifier } from "src/L2/interfaces/ICrossL2Inbox.sol"; /// @notice Thrown when a non-written slot in transient storage is attempted to be read from. error NotEntered(); @@ -69,8 +72,8 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { uint16 public constant messageVersion = uint16(0); /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.11 - string public constant version = "1.0.0-beta.11"; + /// @custom:semver 1.0.0-beta.12 + string public constant version = "1.0.0-beta.12"; /// @notice Mapping of message hashes to boolean receipt values. Note that a message will only be present in this /// mapping if it has successfully been relayed on this chain, and can therefore not be relayed again. @@ -164,7 +167,7 @@ contract L2ToL2CrossDomainMessenger is ISemver, TransientReentrancyAware { } // Signal that this is a cross chain call that needs to have the identifier validated - CrossL2Inbox(Predeploys.CROSS_L2_INBOX).validateMessage(_id, keccak256(_sentMessage)); + ICrossL2Inbox(Predeploys.CROSS_L2_INBOX).validateMessage(_id, keccak256(_sentMessage)); // Decode the payload (uint256 destination, address target, uint256 nonce, address sender, bytes memory message) = diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index 86f73f1d6f9..b39f544f47e 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; -import { IOptimismSuperchainERC20 } from "src/L2/interfaces/IOptimismSuperchainERC20.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol"; +// Contracts import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol"; +import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; import { ZeroAddress, Unauthorized } from "src/libraries/errors/CommonErrors.sol"; +// Interfaces +import { IOptimismSuperchainERC20 } from "src/L2/interfaces/IOptimismSuperchainERC20.sol"; + /// @custom:proxied true /// @title OptimismSuperchainERC20 /// @notice OptimismSuperchainERC20 is a standard extension of the base ERC20 token contract that unifies ERC20 token @@ -58,8 +63,8 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable { } /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.10 - string public constant override version = "1.0.0-beta.10"; + /// @custom:semver 1.0.0-beta.11 + string public constant override version = "1.0.0-beta.11"; /// @notice Constructs the OptimismSuperchainERC20 contract. constructor() { diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol index e2b3dc437b0..3ac981f0742 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces import { IBeacon } from "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; /// @custom:proxied true /// @custom:predeployed 0x4200000000000000000000000000000000000027 @@ -11,8 +14,8 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; /// @notice OptimismSuperchainERC20Beacon is the beacon proxy for the OptimismSuperchainERC20 implementation. contract OptimismSuperchainERC20Beacon is IBeacon, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.2 - string public constant version = "1.0.0-beta.2"; + /// @custom:semver 1.0.0-beta.3 + string public constant version = "1.0.0-beta.3"; /// @inheritdoc IBeacon function implementation() external pure override returns (address) { diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol index 454e3b455d6..4639c72c68a 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol @@ -1,11 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; +// Contracts import { BeaconProxy } from "@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; + +// Libraries import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @custom:proxied /// @custom:predeployed 0x4200000000000000000000000000000000000026 @@ -22,8 +27,8 @@ contract OptimismSuperchainERC20Factory is ISemver { ); /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.4 - string public constant version = "1.0.0-beta.4"; + /// @custom:semver 1.0.0-beta.5 + string public constant version = "1.0.0-beta.5"; /// @notice Mapping of the deployed OptimismSuperchainERC20 to the remote token address. /// This is used to keep track of the token deployments. diff --git a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol index 69a78219e5b..71861c828f4 100644 --- a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol @@ -1,19 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; +// Contracts import { FeeVault } from "src/L2/FeeVault.sol"; +// Libraries import { Types } from "src/libraries/Types.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000011 /// @title SequencerFeeVault /// @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during /// transaction processing and block production. contract SequencerFeeVault is FeeVault, ISemver { - /// @custom:semver 1.5.0-beta.3 - string public constant version = "1.5.0-beta.3"; + /// @custom:semver 1.5.0-beta.4 + string public constant version = "1.5.0-beta.4"; /// @notice Constructs the SequencerFeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol index 6d40ff94376..10273d9bd36 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -1,21 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; -import { IERC7802, IERC165 } from "src/L2/interfaces/IERC7802.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; +// Contracts import { ERC20 } from "@solady-v0.0.245/tokens/ERC20.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; import { Unauthorized } from "src/libraries/errors/CommonErrors.sol"; +// Interfaces +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IERC7802, IERC165 } from "src/L2/interfaces/IERC7802.sol"; + /// @title SuperchainERC20 /// @notice A standard ERC20 extension implementing IERC7802 for unified cross-chain fungibility across /// the Superchain. Allows the SuperchainTokenBridge to mint and burn tokens as needed. abstract contract SuperchainERC20 is ERC20, IERC7802, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.6 + /// @custom:semver 1.0.0-beta.7 function version() external view virtual returns (string memory) { - return "1.0.0-beta.6"; + return "1.0.0-beta.7"; } /// @notice Allows the SuperchainTokenBridge to mint tokens. diff --git a/packages/contracts-bedrock/src/asterisc/RISCV.sol b/packages/contracts-bedrock/src/asterisc/RISCV.sol index 8b0bbb5d1d7..50afd85fe6c 100644 --- a/packages/contracts-bedrock/src/asterisc/RISCV.sol +++ b/packages/contracts-bedrock/src/asterisc/RISCV.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Interfaces import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; @@ -15,8 +16,8 @@ contract RISCV is IBigStepper { IPreimageOracle public oracle; /// @notice The version of the contract. - /// @custom:semver 1.1.0-rc.2 - string public constant version = "1.1.0-rc.2"; + /// @custom:semver 1.1.0-rc.3 + string public constant version = "1.1.0-rc.3"; /// @param _oracle The preimage oracle contract. constructor(IPreimageOracle _oracle) { diff --git a/packages/contracts-bedrock/src/cannon/MIPS.sol b/packages/contracts-bedrock/src/cannon/MIPS.sol index 5efab0ce98f..62b3084f74a 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS.sol @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; +// Libraries import { MIPSInstructions as ins } from "src/cannon/libraries/MIPSInstructions.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { InvalidRMWInstruction } from "src/cannon/libraries/CannonErrors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; + /// @title MIPS /// @notice The MIPS contract emulates a single MIPS instruction. /// Note that delay slots are isolated instructions: @@ -44,8 +47,8 @@ contract MIPS is ISemver { } /// @notice The semantic version of the MIPS contract. - /// @custom:semver 1.2.1-beta.7 - string public constant version = "1.2.1-beta.7"; + /// @custom:semver 1.2.1-beta.8 + string public constant version = "1.2.1-beta.8"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; diff --git a/packages/contracts-bedrock/src/cannon/MIPS2.sol b/packages/contracts-bedrock/src/cannon/MIPS2.sol index 1d73473fde2..d28238980f3 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS2.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS2.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; +// Libraries import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; @@ -12,6 +11,10 @@ import { InvalidMemoryProof, InvalidRMWInstruction, InvalidSecondMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; + /// @title MIPS2 /// @notice The MIPS2 contract emulates a single MIPS instruction. /// It differs from MIPS.sol in that it supports multi-threading. @@ -60,8 +63,8 @@ contract MIPS2 is ISemver { } /// @notice The semantic version of the MIPS2 contract. - /// @custom:semver 1.0.0-beta.22 - string public constant version = "1.0.0-beta.22"; + /// @custom:semver 1.0.0-beta.23 + string public constant version = "1.0.0-beta.23"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; diff --git a/packages/contracts-bedrock/src/cannon/MIPS64.sol b/packages/contracts-bedrock/src/cannon/MIPS64.sol index 53dd0649405..bb2f4369c2a 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS64.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS64.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; +// Libraries import { MIPS64Memory } from "src/cannon/libraries/MIPS64Memory.sol"; import { MIPS64Syscalls as sys } from "src/cannon/libraries/MIPS64Syscalls.sol"; import { MIPS64State as st } from "src/cannon/libraries/MIPS64State.sol"; @@ -13,6 +12,10 @@ import { InvalidMemoryProof, InvalidRMWInstruction, InvalidSecondMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; + /// @title MIPS64 /// @notice The MIPS64 contract emulates a single MIPS instruction. /// It differs from MIPS.sol in that it supports MIPS64 instructions and multi-tasking. @@ -64,8 +67,8 @@ contract MIPS64 is ISemver { } /// @notice The semantic version of the MIPS64 contract. - /// @custom:semver 1.0.0-beta.4 - string public constant version = "1.0.0-beta.4"; + /// @custom:semver 1.0.0-beta.5 + string public constant version = "1.0.0-beta.5"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Instructions.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Instructions.sol index d24ec036e81..7494135ace1 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Instructions.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Instructions.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { MIPS64Memory } from "src/cannon/libraries/MIPS64Memory.sol"; import { MIPS64State as st } from "src/cannon/libraries/MIPS64State.sol"; import { MIPS64Arch as arch } from "src/cannon/libraries/MIPS64Arch.sol"; diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Memory.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Memory.sol index 9ed97396e10..f6e0633466e 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Memory.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Memory.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { InvalidMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; library MIPS64Memory { diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPS64State.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPS64State.sol index 09678148f3e..09c347841b9 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPS64State.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPS64State.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol"; library MIPS64State { diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol index 10954c64748..d4b706da4b5 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPS64Syscalls.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { MIPS64Memory } from "src/cannon/libraries/MIPS64Memory.sol"; import { MIPS64State as st } from "src/cannon/libraries/MIPS64State.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol index fa4d1451b54..f2af43da0fe 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol index 015955954b5..b78cc04a895 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { InvalidMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; library MIPSMemory { diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol index f9631e29e08..22fb608bcf5 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol"; library MIPSState { diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol index ec0cfdded89..8e3516c0c1e 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; diff --git a/packages/contracts-bedrock/src/dispute/lib/Errors.sol b/packages/contracts-bedrock/src/dispute/lib/Errors.sol index 6e95bfa5a34..0dd4af18750 100644 --- a/packages/contracts-bedrock/src/dispute/lib/Errors.sol +++ b/packages/contracts-bedrock/src/dispute/lib/Errors.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Libraries import { GameType, Hash, Claim } from "src/dispute/lib/LibUDT.sol"; //////////////////////////////////////////////////////////////// diff --git a/packages/contracts-bedrock/src/dispute/lib/LibUDT.sol b/packages/contracts-bedrock/src/dispute/lib/LibUDT.sol index bfc110f0952..780738a7974 100644 --- a/packages/contracts-bedrock/src/dispute/lib/LibUDT.sol +++ b/packages/contracts-bedrock/src/dispute/lib/LibUDT.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Libraries import { Position } from "src/dispute/lib/LibPosition.sol"; using LibClaim for Claim global; diff --git a/packages/contracts-bedrock/src/dispute/lib/Types.sol b/packages/contracts-bedrock/src/dispute/lib/Types.sol index 70df7b7912b..74106888fb0 100644 --- a/packages/contracts-bedrock/src/dispute/lib/Types.sol +++ b/packages/contracts-bedrock/src/dispute/lib/Types.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Libraries import { Position, Hash, diff --git a/packages/contracts-bedrock/src/governance/GovernanceToken.sol b/packages/contracts-bedrock/src/governance/GovernanceToken.sol index 6fb1041555a..3843c3241b2 100644 --- a/packages/contracts-bedrock/src/governance/GovernanceToken.sol +++ b/packages/contracts-bedrock/src/governance/GovernanceToken.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20Burnable } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { ERC20Votes, ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; diff --git a/packages/contracts-bedrock/src/legacy/AddressManager.sol b/packages/contracts-bedrock/src/legacy/AddressManager.sol index daaac412e0a..e3b2e9274cc 100644 --- a/packages/contracts-bedrock/src/legacy/AddressManager.sol +++ b/packages/contracts-bedrock/src/legacy/AddressManager.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /// @custom:legacy true diff --git a/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol b/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol index a7a6313edf4..e247f65ffb9 100644 --- a/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol +++ b/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @custom:legacy true @@ -41,8 +42,8 @@ contract DeployerWhitelist is ISemver { } /// @notice Semantic version. - /// @custom:semver 1.1.1-beta.1 - string public constant version = "1.1.1-beta.1"; + /// @custom:semver 1.1.1-beta.2 + string public constant version = "1.1.1-beta.2"; /// @notice Adds or removes an address from the deployment whitelist. /// @param _deployer Address to update permissions for. diff --git a/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol b/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol index 28125a23f90..b6a5363e2fb 100644 --- a/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol +++ b/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { Constants } from "src/libraries/Constants.sol"; + +// Interfaces import { IL1ChugSplashDeployer } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; /// @custom:legacy true diff --git a/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol b/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol index b90d1263f7a..d215f29bdc7 100644 --- a/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol +++ b/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @custom:legacy true @@ -14,8 +15,8 @@ contract LegacyMessagePasser is ISemver { mapping(bytes32 => bool) public sentMessages; /// @notice Semantic version. - /// @custom:semver 1.1.1-beta.1 - string public constant version = "1.1.1-beta.1"; + /// @custom:semver 1.1.1-beta.2 + string public constant version = "1.1.1-beta.2"; /// @notice Passes a message to L1. /// @param _message Message to pass to L1. diff --git a/packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol b/packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol index b3b58825824..8efd0bf0c49 100644 --- a/packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol +++ b/packages/contracts-bedrock/src/legacy/LegacyMintableERC20.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +// Interfaces import { ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; /// @title LegacyMintableERC20 diff --git a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol index 3005456570f..d4e4a96f7ff 100644 --- a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol +++ b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { AddressManager } from "src/legacy/AddressManager.sol"; /// @custom:legacy true diff --git a/packages/contracts-bedrock/src/libraries/Arithmetic.sol b/packages/contracts-bedrock/src/libraries/Arithmetic.sol index dfd47274f7f..140affaa718 100644 --- a/packages/contracts-bedrock/src/libraries/Arithmetic.sol +++ b/packages/contracts-bedrock/src/libraries/Arithmetic.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Libraries import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol"; import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; diff --git a/packages/contracts-bedrock/src/libraries/Constants.sol b/packages/contracts-bedrock/src/libraries/Constants.sol index 1cbd61d21a5..6a99410b5bc 100644 --- a/packages/contracts-bedrock/src/libraries/Constants.sol +++ b/packages/contracts-bedrock/src/libraries/Constants.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Interfaces import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; /// @title Constants diff --git a/packages/contracts-bedrock/src/libraries/Encoding.sol b/packages/contracts-bedrock/src/libraries/Encoding.sol index 84d5f732f5f..5aa4ee7d3d8 100644 --- a/packages/contracts-bedrock/src/libraries/Encoding.sol +++ b/packages/contracts-bedrock/src/libraries/Encoding.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { RLPWriter } from "src/libraries/rlp/RLPWriter.sol"; diff --git a/packages/contracts-bedrock/src/libraries/GasPayingToken.sol b/packages/contracts-bedrock/src/libraries/GasPayingToken.sol index 37c06840bd5..bf53367476b 100644 --- a/packages/contracts-bedrock/src/libraries/GasPayingToken.sol +++ b/packages/contracts-bedrock/src/libraries/GasPayingToken.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Libraries +import { LibString } from "@solady/utils/LibString.sol"; import { Storage } from "src/libraries/Storage.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { LibString } from "@solady/utils/LibString.sol"; /// @title IGasToken /// @notice Implemented by contracts that are aware of the custom gas token used diff --git a/packages/contracts-bedrock/src/libraries/Hashing.sol b/packages/contracts-bedrock/src/libraries/Hashing.sol index 0f0f15678f9..b736ad9e4b7 100644 --- a/packages/contracts-bedrock/src/libraries/Hashing.sol +++ b/packages/contracts-bedrock/src/libraries/Hashing.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Libraries import { Types } from "src/libraries/Types.sol"; import { Encoding } from "src/libraries/Encoding.sol"; diff --git a/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol b/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol index 559c53391f7..f342658cb45 100644 --- a/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol +++ b/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.8; +// Libraries import { EmptyItem, UnexpectedString, @@ -8,7 +9,7 @@ import { ContentLengthMismatch, InvalidHeader, UnexpectedList -} from "./RLPErrors.sol"; +} from "src/libraries/rlp/RLPErrors.sol"; /// @custom:attribution https://github.com/hamdiallam/Solidity-RLP /// @title RLPReader diff --git a/packages/contracts-bedrock/src/libraries/trie/MerkleTrie.sol b/packages/contracts-bedrock/src/libraries/trie/MerkleTrie.sol index fa500894b16..cbbf9fdf3d6 100644 --- a/packages/contracts-bedrock/src/libraries/trie/MerkleTrie.sol +++ b/packages/contracts-bedrock/src/libraries/trie/MerkleTrie.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Bytes } from "../Bytes.sol"; -import { RLPReader } from "../rlp/RLPReader.sol"; +// Libraries +import { Bytes } from "src/libraries/Bytes.sol"; +import { RLPReader } from "src/libraries/rlp/RLPReader.sol"; /// @title MerkleTrie /// @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie diff --git a/packages/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol b/packages/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol index e8eab17917a..56992fba997 100644 --- a/packages/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol +++ b/packages/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { MerkleTrie } from "./MerkleTrie.sol"; +// Libraries +import { MerkleTrie } from "src/libraries/trie/MerkleTrie.sol"; /// @title SecureMerkleTrie /// @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input diff --git a/packages/contracts-bedrock/src/periphery/AssetReceiver.sol b/packages/contracts-bedrock/src/periphery/AssetReceiver.sol index ce59d8ef753..0ee2d52a29b 100644 --- a/packages/contracts-bedrock/src/periphery/AssetReceiver.sol +++ b/packages/contracts-bedrock/src/periphery/AssetReceiver.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Contracts import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol"; import { ERC721 } from "@rari-capital/solmate/src/tokens/ERC721.sol"; -import { Transactor } from "./Transactor.sol"; +import { Transactor } from "src/periphery/Transactor.sol"; /// @title AssetReceiver /// @notice AssetReceiver is a minimal contract for receiving funds assets in the form of either diff --git a/packages/contracts-bedrock/src/periphery/Transactor.sol b/packages/contracts-bedrock/src/periphery/Transactor.sol index 01c8cc384ad..168367b4109 100644 --- a/packages/contracts-bedrock/src/periphery/Transactor.sol +++ b/packages/contracts-bedrock/src/periphery/Transactor.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Contracts import { Owned } from "@rari-capital/solmate/src/auth/Owned.sol"; /// @title Transactor diff --git a/packages/contracts-bedrock/src/periphery/TransferOnion.sol b/packages/contracts-bedrock/src/periphery/TransferOnion.sol index db473a1828c..292eb9c3423 100644 --- a/packages/contracts-bedrock/src/periphery/TransferOnion.sol +++ b/packages/contracts-bedrock/src/periphery/TransferOnion.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +// Libraries import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title TransferOnion diff --git a/packages/contracts-bedrock/src/periphery/drippie/Drippie.sol b/packages/contracts-bedrock/src/periphery/drippie/Drippie.sol index 014694813e4..c7240d015a9 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/Drippie.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/Drippie.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { AssetReceiver } from "../AssetReceiver.sol"; -import { IDripCheck } from "./IDripCheck.sol"; +// Contracts +import { AssetReceiver } from "src/periphery/AssetReceiver.sol"; + +// Interfaces +import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; /// @title Drippie /// @notice Drippie is a system for managing automated contract interactions. A specific interaction diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceLow.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceLow.sol index ff7121051c7..d889a4fa442 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceLow.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckBalanceLow.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IDripCheck } from "../IDripCheck.sol"; +// Interfaces +import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; /// @title CheckBalanceLow /// @notice DripCheck for checking if an account's balance is below a given threshold. diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol index a5ef463f89e..7324e451c7d 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IDripCheck } from "../IDripCheck.sol"; +// Interfaces import { IGelatoTreasury } from "src/vendor/interfaces/IGelatoTreasury.sol"; +import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; /// @title CheckGelatoLow /// @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold. diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckSecrets.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckSecrets.sol index 5cfc4251b45..f255c2e6964 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckSecrets.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckSecrets.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IDripCheck } from "../IDripCheck.sol"; +// Interfaces +import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; /// @title CheckSecrets /// @notice DripCheck that checks if specific secrets exist (or not). Supports having a secret that diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckTrue.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckTrue.sol index 1ce7138945c..18d4956f8e6 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckTrue.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckTrue.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IDripCheck } from "../IDripCheck.sol"; +// Interfaces +import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol"; /// @title CheckTrue /// @notice DripCheck that always returns true. diff --git a/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol b/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol index cce6a83b3e1..66cab547317 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IFaucetAuthModule } from "src/periphery/faucet/authmodules/IFaucetAuthModule.sol"; -import { SafeCall } from "src/libraries/SafeCall.sol"; +// Contracts import { SafeSend } from "src/universal/SafeSend.sol"; +// Libraries +import { SafeCall } from "src/libraries/SafeCall.sol"; + +// Interfaces +import { IFaucetAuthModule } from "src/periphery/faucet/authmodules/IFaucetAuthModule.sol"; + /// @title Faucet /// @notice Faucet contract that drips ETH to users. contract Faucet { diff --git a/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol b/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol index 115810d9d13..c9077943610 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; -import { IFaucetAuthModule } from "./IFaucetAuthModule.sol"; -import { Faucet } from "../Faucet.sol"; + +// Interfaces +import { IFaucetAuthModule } from "src/periphery/faucet/authmodules/IFaucetAuthModule.sol"; +import { Faucet } from "src/periphery/faucet/Faucet.sol"; /// @title AdminFaucetAuthModule /// @notice FaucetAuthModule that allows an admin to sign off on a given faucet drip. Takes an admin diff --git a/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol b/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol index a94071dd2be..b4d91febf4a 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Faucet } from "../Faucet.sol"; +// Contracts +import { Faucet } from "src/periphery/faucet/Faucet.sol"; /// @title IFaucetAuthModule /// @notice Interface for faucet authentication modules. diff --git a/packages/contracts-bedrock/src/safe/LivenessGuard.sol b/packages/contracts-bedrock/src/safe/LivenessGuard.sol index aa9a231a4b2..f5966a9e146 100644 --- a/packages/contracts-bedrock/src/safe/LivenessGuard.sol +++ b/packages/contracts-bedrock/src/safe/LivenessGuard.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Safe import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { Guard as BaseGuard } from "safe-contracts/base/GuardManager.sol"; -import { SafeSigners } from "src/safe/SafeSigners.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +// Libraries import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import { SafeSigners } from "src/safe/SafeSigners.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title LivenessGuard /// @notice This Guard contract is used to track the liveness of Safe owners. @@ -25,8 +30,8 @@ contract LivenessGuard is ISemver, BaseGuard { event OwnerRecorded(address owner); /// @notice Semantic version. - /// @custom:semver 1.0.1-beta.2 - string public constant version = "1.0.1-beta.2"; + /// @custom:semver 1.0.1-beta.3 + string public constant version = "1.0.1-beta.3"; /// @notice The safe account for which this contract will be the guard. Safe internal immutable SAFE; diff --git a/packages/contracts-bedrock/src/safe/LivenessModule.sol b/packages/contracts-bedrock/src/safe/LivenessModule.sol index cd41c6e2dd5..50ab03d450c 100644 --- a/packages/contracts-bedrock/src/safe/LivenessModule.sol +++ b/packages/contracts-bedrock/src/safe/LivenessModule.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Safe import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; import { OwnerManager } from "safe-contracts/base/OwnerManager.sol"; + +// Contracts import { LivenessGuard } from "src/safe/LivenessGuard.sol"; + +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title LivenessModule @@ -53,8 +58,8 @@ contract LivenessModule is ISemver { uint256 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8; /// @notice Semantic version. - /// @custom:semver 1.2.1-beta.1 - string public constant version = "1.2.1-beta.1"; + /// @custom:semver 1.2.1-beta.2 + string public constant version = "1.2.1-beta.2"; // Constructor to initialize the Safe and baseModule instances constructor( diff --git a/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol b/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol index 66c724d3eba..85d801f0a1a 100644 --- a/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; import { Hashing } from "src/libraries/Hashing.sol"; diff --git a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol index 52217fab713..3c6d7fe816f 100644 --- a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; -import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +// Libraries +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; + +// Interfaces +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + /// @title ERC721Bridge /// @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges. abstract contract ERC721Bridge is Initializable { diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol index 34d601cbb65..0e25cd33938 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol @@ -1,13 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol"; + +// Libraries +import { Preinstalls } from "src/libraries/Preinstalls.sol"; + +// Interfaces import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IOptimismMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; import { ILegacyMintableERC20 } from "src/universal/interfaces/ILegacyMintableERC20.sol"; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { Preinstalls } from "src/libraries/Preinstalls.sol"; /// @title OptimismMintableERC20 /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed @@ -42,8 +47,8 @@ contract OptimismMintableERC20 is ERC20Permit, ISemver { } /// @notice Semantic version. - /// @custom:semver 1.4.0-beta.2 - string public constant version = "1.4.0-beta.2"; + /// @custom:semver 1.4.0-beta.3 + string public constant version = "1.4.0-beta.3"; /// @notice Getter function for the permit2 address. It deterministically deployed /// so it will always be at the same address. It is also included as a preinstall, diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol index d7a9cd3372c..4f4b01602cc 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; + +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; -import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; /// @custom:proxied true @@ -48,8 +51,8 @@ contract OptimismMintableERC20Factory is ISemver, Initializable, IOptimismERC20F /// the OptimismMintableERC20 token contract since this contract /// is responsible for deploying OptimismMintableERC20 contracts. /// @notice Semantic version. - /// @custom:semver 1.10.1-beta.4 - string public constant version = "1.10.1-beta.4"; + /// @custom:semver 1.10.1-beta.5 + string public constant version = "1.10.1-beta.5"; /// @notice Constructs the OptimismMintableERC20Factory contract. constructor() { diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol index 9dd05e10d1f..140c6ce5e6d 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol @@ -1,11 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +// Libraries import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { IOptimismMintableERC721 } from "src/universal/interfaces/IOptimismMintableERC721.sol"; + +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IOptimismMintableERC721 } from "src/universal/interfaces/IOptimismMintableERC721.sol"; /// @title OptimismMintableERC721 /// @notice This contract is the remote representation for some token that lives on another network, @@ -41,8 +46,8 @@ contract OptimismMintableERC721 is ERC721Enumerable, ISemver { } /// @notice Semantic version. - /// @custom:semver 1.3.1-beta.3 - string public constant version = "1.3.1-beta.3"; + /// @custom:semver 1.3.1-beta.4 + string public constant version = "1.3.1-beta.4"; /// @param _bridge Address of the bridge on this network. /// @param _remoteChainId Chain ID where the remote token is deployed. diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol index 7350e0fae0d..da05e8f4f34 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol"; + +// Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title OptimismMintableERC721Factory @@ -25,8 +28,8 @@ contract OptimismMintableERC721Factory is ISemver { event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer); /// @notice Semantic version. - /// @custom:semver 1.4.1-beta.4 - string public constant version = "1.4.1-beta.4"; + /// @custom:semver 1.4.1-beta.5 + string public constant version = "1.4.1-beta.5"; /// @notice The semver MUST be bumped any time that there is a change in /// the OptimismMintableERC721 token contract since this contract diff --git a/packages/contracts-bedrock/src/universal/Proxy.sol b/packages/contracts-bedrock/src/universal/Proxy.sol index b50b08efca8..4fd53dae06b 100644 --- a/packages/contracts-bedrock/src/universal/Proxy.sol +++ b/packages/contracts-bedrock/src/universal/Proxy.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Libraries import { Constants } from "src/libraries/Constants.sol"; /// @title Proxy diff --git a/packages/contracts-bedrock/src/universal/StandardBridge.sol b/packages/contracts-bedrock/src/universal/StandardBridge.sol index 57af2247a65..dceb2fd4147 100644 --- a/packages/contracts-bedrock/src/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/src/universal/StandardBridge.sol @@ -1,17 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +// Contracts +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +// Libraries import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +// Interfaces +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IOptimismMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; import { ILegacyMintableERC20 } from "src/universal/interfaces/ILegacyMintableERC20.sol"; import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { Constants } from "src/libraries/Constants.sol"; /// @custom:upgradeable /// @title StandardBridge @@ -294,7 +298,7 @@ abstract contract StandardBridge is Initializable { "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" ); - OptimismMintableERC20(_localToken).mint(_to, _amount); + IOptimismMintableERC20(_localToken).mint(_to, _amount); } else { deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount; IERC20(_localToken).safeTransfer(_to, _amount); @@ -364,7 +368,7 @@ abstract contract StandardBridge is Initializable { "StandardBridge: wrong remote token for Optimism Mintable ERC20 local token" ); - OptimismMintableERC20(_localToken).burn(_from, _amount); + IOptimismMintableERC20(_localToken).burn(_from, _amount); } else { IERC20(_localToken).safeTransferFrom(_from, address(this), _amount); deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount; diff --git a/packages/contracts-bedrock/src/universal/StorageSetter.sol b/packages/contracts-bedrock/src/universal/StorageSetter.sol index 5bd53a75b36..e6e4b5df545 100644 --- a/packages/contracts-bedrock/src/universal/StorageSetter.sol +++ b/packages/contracts-bedrock/src/universal/StorageSetter.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/interfaces/ISemver.sol"; +// Libraries import { Storage } from "src/libraries/Storage.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @title StorageSetter /// @notice A simple contract that allows setting arbitrary storage slots. /// WARNING: this contract is not safe to be called by untrusted parties. @@ -16,8 +19,8 @@ contract StorageSetter is ISemver { } /// @notice Semantic version. - /// @custom:semver 1.2.1-beta.2 - string public constant version = "1.2.1-beta.2"; + /// @custom:semver 1.2.1-beta.3 + string public constant version = "1.2.1-beta.3"; /// @notice Stores a bytes32 `_value` at `_slot`. Any storage slots that /// are packed should be set through this interface. diff --git a/packages/contracts-bedrock/src/vendor/eas/resolver/ISchemaResolver.sol b/packages/contracts-bedrock/src/vendor/eas/resolver/ISchemaResolver.sol index 51aac1ece23..d2089f83af8 100644 --- a/packages/contracts-bedrock/src/vendor/eas/resolver/ISchemaResolver.sol +++ b/packages/contracts-bedrock/src/vendor/eas/resolver/ISchemaResolver.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Attestation } from "../Common.sol"; +import { Attestation } from "src/vendor/eas/Common.sol"; /// @title ISchemaResolver /// @notice The interface of an optional schema resolver. diff --git a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol index bd6d3b5d7de..c39bf0ee0f7 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries @@ -9,12 +9,8 @@ import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import "src/libraries/PortalErrors.sol"; -// Target contract dependencies -import "src/libraries/PortalErrors.sol"; -import { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; - // Interfaces +import { IL1BlockInterop, ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; contract OptimismPortalInterop_Test is CommonTest { @@ -35,7 +31,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value)) + _data: abi.encodeCall(IL1BlockInterop.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); @@ -58,7 +54,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.ADD_DEPENDENCY, _value)) + _data: abi.encodeCall(IL1BlockInterop.setConfig, (ConfigType.ADD_DEPENDENCY, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); @@ -81,7 +77,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.REMOVE_DEPENDENCY, _value)) + _data: abi.encodeCall(IL1BlockInterop.setConfig, (ConfigType.REMOVE_DEPENDENCY, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol index 78337fc3b4d..5132dc40e04 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol @@ -6,7 +6,6 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { ConfigType } from "src/L2/L1BlockInterop.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; @@ -17,6 +16,7 @@ import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; +import { ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; contract SystemConfigInterop_Test is CommonTest { /// @notice Marked virtual to be overridden in diff --git a/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol b/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol index c8779342c3b..01d3e6108f9 100644 --- a/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol +++ b/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { StaticConfig } from "src/libraries/StaticConfig.sol"; - -// Target contract dependencies -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import "src/libraries/L1BlockErrors.sol"; +// Interfaces +import { IL1BlockInterop, ConfigType } from "src/L2/interfaces/IL1BlockInterop.sol"; + contract L1BlockInteropTest is CommonTest { event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); event DependencyAdded(uint256 indexed chainId); @@ -199,8 +199,8 @@ contract L1BlockInteropTest is CommonTest { } /// @dev Returns the L1BlockInterop instance. - function _l1BlockInterop() internal view returns (L1BlockInterop) { - return L1BlockInterop(address(l1Block)); + function _l1BlockInterop() internal view returns (IL1BlockInterop) { + return IL1BlockInterop(address(l1Block)); } } @@ -261,7 +261,7 @@ contract L1BlockInteropSetL1BlockValuesInterop_Test is L1BlockInteropTest { vm.prank(_l1BlockInterop().DEPOSITOR_ACCOUNT()); (bool success,) = address(l1Block).call( - abi.encodePacked(L1BlockInterop.setL1BlockValuesInterop.selector, setValuesEcotoneCalldata) + abi.encodePacked(IL1BlockInterop.setL1BlockValuesInterop.selector, setValuesEcotoneCalldata) ); assertTrue(success, "function call failed"); diff --git a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol index 0775eb588d2..fcfa375c1b5 100644 --- a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol @@ -10,7 +10,6 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { Hashing } from "src/libraries/Hashing.sol"; // Target contract -import { CrossL2Inbox, Identifier } from "src/L2/CrossL2Inbox.sol"; import { L2ToL2CrossDomainMessenger, NotEntered, @@ -27,6 +26,9 @@ import { InvalidChainId } from "src/L2/L2ToL2CrossDomainMessenger.sol"; +// Interfaces +import { ICrossL2Inbox, Identifier } from "src/L2/interfaces/ICrossL2Inbox.sol"; + /// @title L2ToL2CrossDomainMessengerWithModifiableTransientStorage /// @dev L2ToL2CrossDomainMessenger contract with methods to modify the transient storage. /// This is used to test the transient storage of L2ToL2CrossDomainMessenger. @@ -264,7 +266,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -308,7 +310,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -371,7 +373,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -452,7 +454,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -534,7 +536,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -573,7 +575,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -615,7 +617,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -665,7 +667,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); @@ -715,7 +717,7 @@ contract L2ToL2CrossDomainMessengerTest is Test { // Ensure the CrossL2Inbox validates this message vm.mockCall({ callee: Predeploys.CROSS_L2_INBOX, - data: abi.encodeCall(CrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), + data: abi.encodeCall(ICrossL2Inbox.validateMessage, (id, keccak256(sentMessage))), returnData: "" }); diff --git a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol index aa8d2545106..203605f3b1b 100644 --- a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol @@ -4,16 +4,16 @@ pragma solidity 0.8.15; // Testing import { Test } from "forge-std/Test.sol"; -// Contracts -import { IL1BlockNumber } from "src/legacy/interfaces/IL1BlockNumber.sol"; -import { L1Block } from "src/L2/L1Block.sol"; - // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; +// Interfaces +import { IL1BlockNumber } from "src/legacy/interfaces/IL1BlockNumber.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + contract L1BlockNumberTest is Test { - L1Block lb; + IL1Block lb; IL1BlockNumber bn; uint64 constant number = 99; @@ -21,7 +21,7 @@ contract L1BlockNumberTest is Test { /// @dev Sets up the test suite. function setUp() external { vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, vm.getDeployedCode("L1Block.sol:L1Block")); - lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); + lb = IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES); bn = IL1BlockNumber( DeployUtils.create1({ _name: "L1BlockNumber", From 9fb5aa2eb3291402bbc8822535f2889abc5e9ae5 Mon Sep 17 00:00:00 2001 From: George Knee Date: Mon, 25 Nov 2024 22:22:32 +0000 Subject: [PATCH 29/61] upload to codecov using orb (#13062) --- .circleci/config.yml | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 789ce0b8c56..8e25f5b509a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,6 +53,7 @@ orbs: gcp-cli: circleci/gcp-cli@3.0.1 slack: circleci/slack@4.10.1 shellcheck: circleci/shellcheck@3.2.0 + codecov: codecov/codecov@5.0.3 commands: gcp-oidc-authenticate: description: "Authenticate with GCP using a CircleCI OIDC token." @@ -202,10 +203,10 @@ jobs: gotestsum --format=testname --junitfile=../tmp/test-results/cannon-32.xml --jsonfile=../tmp/testlogs/log-32.json \ -- -parallel=$(nproc) -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage-32.out ./... working_directory: cannon - - run: - name: Upload Cannon coverage - command: codecov --verbose --clean --flags cannon-go-tests-32 -f ./coverage-32.out - working_directory: cannon + - codecov/upload: + disable_search: true + files: ./cannon/coverage-32.out + flags: cannon-go-tests-32 - when: condition: equal: [64, <>] @@ -217,10 +218,10 @@ jobs: gotestsum --format=testname --junitfile=../tmp/test-results/cannon-64.xml --jsonfile=../tmp/testlogs/log-64.json \ -- --tags=cannon64 -parallel=$(nproc) -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage-64.out ./... working_directory: cannon - - run: - name: Upload Cannon coverage - command: codecov --verbose --clean --flags cannon-go-tests-64 -f ./coverage-64.out - working_directory: cannon + - codecov/upload: + disable_search: true + files: ./cannon/coverage-64.out + flags: cannon-go-tests-64 - store_test_results: path: ./tmp/test-results - store_artifacts: @@ -606,11 +607,10 @@ jobs: environment: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock - - run: - name: upload coverage - command: codecov --verbose --clean --flags contracts-bedrock-tests - environment: - FOUNDRY_PROFILE: ci + - codecov/upload: + disable_search: true + files: ./packages/contracts-bedrock/coverage/lcov.info + flags: contracts-bedrock-tests contracts-bedrock-tests: docker: @@ -903,7 +903,7 @@ jobs: no_output_timeout: <> command: | mkdir -p ./tmp/test-results && mkdir -p ./tmp/testlogs - + cd op-e2e && make pre-test && cd .. packages=( @@ -920,7 +920,7 @@ jobs: export ENABLE_ANVIL=true export SEPOLIA_RPC_URL="https://ci-sepolia-l1-archive.optimism.io" export MAINNET_RPC_URL="https://ci-mainnet-l1-archive.optimism.io" - + <> gotestsum --format=testname \ @@ -929,6 +929,9 @@ jobs: --rerun-fails=2 \ --packages="$formatted_packages" \ -- -coverprofile=coverage.out -timeout=60m + - codecov/upload: + disable_search: true + files: ./coverage.out - store_test_results: path: ./tmp/test-results - store_artifacts: From 70d90208f430488d7d2ab611a44e8c71bbe0c106 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 25 Nov 2024 17:35:09 -0500 Subject: [PATCH 30/61] feat: reorder Deploy.s.sol helpers (#13084) * feat: delete unused deploy functions * feat: Delete some more unused code * fix: Unused imports * feat: reorder Deploy.s.sol helpers --- .../scripts/deploy/Deploy.s.sol | 118 +++++++++--------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index bfe062370a6..2cbed1c5568 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -180,28 +180,6 @@ contract Deploy is Deployer { }); } - //////////////////////////////////////////////////////////////// - // State Changing Helper Functions // - //////////////////////////////////////////////////////////////// - - /// @notice Transfer ownership of the ProxyAdmin contract to the final system owner - function transferProxyAdminOwnership() public broadcast { - // Get the ProxyAdmin contract. - IProxyAdmin proxyAdmin = IProxyAdmin(mustGetAddress("ProxyAdmin")); - - // Transfer ownership to the final system owner if necessary. - address owner = proxyAdmin.owner(); - address finalSystemOwner = cfg.finalSystemOwner(); - if (owner != finalSystemOwner) { - proxyAdmin.transferOwnership(finalSystemOwner); - console.log("ProxyAdmin ownership transferred to final system owner at: %s", finalSystemOwner); - } - - // Make sure the ProxyAdmin owner is set to the final system owner. - owner = proxyAdmin.owner(); - require(owner == finalSystemOwner, "Deploy: ProxyAdmin ownership not transferred to final system owner"); - } - //////////////////////////////////////////////////////////////// // SetUp and Run // //////////////////////////////////////////////////////////////// @@ -304,7 +282,7 @@ contract Deploy is Deployer { bytes32 typeHash = keccak256(bytes(cfg.daCommitmentType())); bytes32 keccakHash = keccak256(bytes("KeccakCommitment")); if (typeHash == keccakHash) { - setupOpAltDA(); + deployOpAltDA(); } } @@ -488,7 +466,7 @@ contract Deploy is Deployer { } /// @notice Add AltDA setup to the OP chain - function setupOpAltDA() public { + function deployOpAltDA() public { console.log("Deploying OP AltDA"); deployDataAvailabilityChallengeProxy(); deployDataAvailabilityChallenge(); @@ -729,6 +707,61 @@ contract Deploy is Deployer { ChainAssertions.checkOptimismPortal({ _contracts: _proxies(), _cfg: cfg, _isProxy: true }); } + /// @notice Initialize the DataAvailabilityChallenge + function initializeDataAvailabilityChallenge() public broadcast { + console.log("Upgrading and initializing DataAvailabilityChallenge proxy"); + address dataAvailabilityChallengeProxy = mustGetAddress("DataAvailabilityChallengeProxy"); + address dataAvailabilityChallenge = mustGetAddress("DataAvailabilityChallenge"); + + address finalSystemOwner = cfg.finalSystemOwner(); + uint256 daChallengeWindow = cfg.daChallengeWindow(); + uint256 daResolveWindow = cfg.daResolveWindow(); + uint256 daBondSize = cfg.daBondSize(); + uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage(); + + IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin"))); + proxyAdmin.upgradeAndCall({ + _proxy: payable(dataAvailabilityChallengeProxy), + _implementation: dataAvailabilityChallenge, + _data: abi.encodeCall( + IDataAvailabilityChallenge.initialize, + (finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage) + ) + }); + + IDataAvailabilityChallenge dac = IDataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy)); + string memory version = dac.version(); + console.log("DataAvailabilityChallenge version: %s", version); + + require(dac.owner() == finalSystemOwner); + require(dac.challengeWindow() == daChallengeWindow); + require(dac.resolveWindow() == daResolveWindow); + require(dac.bondSize() == daBondSize); + require(dac.resolverRefundPercentage() == daResolverRefundPercentage); + } + + //////////////////////////////////////////////////////////////// + // Ownership Transfer Helper Functions // + //////////////////////////////////////////////////////////////// + + /// @notice Transfer ownership of the ProxyAdmin contract to the final system owner + function transferProxyAdminOwnership() public broadcast { + // Get the ProxyAdmin contract. + IProxyAdmin proxyAdmin = IProxyAdmin(mustGetAddress("ProxyAdmin")); + + // Transfer ownership to the final system owner if necessary. + address owner = proxyAdmin.owner(); + address finalSystemOwner = cfg.finalSystemOwner(); + if (owner != finalSystemOwner) { + proxyAdmin.transferOwnership(finalSystemOwner); + console.log("ProxyAdmin ownership transferred to final system owner at: %s", finalSystemOwner); + } + + // Make sure the ProxyAdmin owner is set to the final system owner. + owner = proxyAdmin.owner(); + require(owner == finalSystemOwner, "Deploy: ProxyAdmin ownership not transferred to final system owner"); + } + /// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner function transferDisputeGameFactoryOwnership() public broadcast { console.log("Transferring DisputeGameFactory ownership to Safe"); @@ -785,6 +818,10 @@ contract Deploy is Deployer { }); } + /////////////////////////////////////////////////////////// + // Proofs setup helper functions // + /////////////////////////////////////////////////////////// + /// @notice Load the appropriate mips absolute prestate for devenets depending on config environment. function loadMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) { if (block.chainid == Chains.LocalDevnet || block.chainid == Chains.GethDevnet) { @@ -984,39 +1021,6 @@ contract Deploy is Deployer { ); } - /// @notice Initialize the DataAvailabilityChallenge - function initializeDataAvailabilityChallenge() public broadcast { - console.log("Upgrading and initializing DataAvailabilityChallenge proxy"); - address dataAvailabilityChallengeProxy = mustGetAddress("DataAvailabilityChallengeProxy"); - address dataAvailabilityChallenge = mustGetAddress("DataAvailabilityChallenge"); - - address finalSystemOwner = cfg.finalSystemOwner(); - uint256 daChallengeWindow = cfg.daChallengeWindow(); - uint256 daResolveWindow = cfg.daResolveWindow(); - uint256 daBondSize = cfg.daBondSize(); - uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage(); - - IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin"))); - proxyAdmin.upgradeAndCall({ - _proxy: payable(dataAvailabilityChallengeProxy), - _implementation: dataAvailabilityChallenge, - _data: abi.encodeCall( - IDataAvailabilityChallenge.initialize, - (finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage) - ) - }); - - IDataAvailabilityChallenge dac = IDataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy)); - string memory version = dac.version(); - console.log("DataAvailabilityChallenge version: %s", version); - - require(dac.owner() == finalSystemOwner); - require(dac.challengeWindow() == daChallengeWindow); - require(dac.resolveWindow() == daResolveWindow); - require(dac.bondSize() == daBondSize); - require(dac.resolverRefundPercentage() == daResolverRefundPercentage); - } - /// @notice Get the DeployInput struct to use for testing function getDeployInput() public view returns (OPContractsManager.DeployInput memory) { OutputRoot memory testOutputRoot = OutputRoot({ From efbe102213d9f66ec77a10f2d6fb65ae09298365 Mon Sep 17 00:00:00 2001 From: Zach Howard Date: Mon, 25 Nov 2024 20:28:45 -0500 Subject: [PATCH 31/61] Use circleci-ip-ranges for fpp-verify (#13093) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e25f5b509a..0368861be01 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1112,6 +1112,7 @@ jobs: - run: echo Done fpp-verify: + circleci_ip_ranges: true docker: - image: cimg/go:1.21 steps: From d5dfd515a844ce16b8488af6a95fd45d95ed7e78 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 26 Nov 2024 11:40:21 +1000 Subject: [PATCH 32/61] op-dispute-mon: Wrap L1 RPC client with timeouts. (#13059) Requires moving from ethclient.Client to sources.L1Client since ethclient.Client requires a *rpc.Client which doesn't have any support for request timeouts. --- op-dispute-mon/mon/extract/head_enricher.go | 8 +-- .../mon/extract/head_enricher_test.go | 11 ++-- op-dispute-mon/mon/monitor.go | 58 +++++++++---------- op-dispute-mon/mon/monitor_test.go | 27 +++------ op-dispute-mon/mon/service.go | 38 +++++++----- 5 files changed, 66 insertions(+), 76 deletions(-) diff --git a/op-dispute-mon/mon/extract/head_enricher.go b/op-dispute-mon/mon/extract/head_enricher.go index 943e648f771..4162c9e896d 100644 --- a/op-dispute-mon/mon/extract/head_enricher.go +++ b/op-dispute-mon/mon/extract/head_enricher.go @@ -5,15 +5,15 @@ import ( "fmt" monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" ) var _ Enricher = (*L1HeadBlockNumEnricher)(nil) type BlockFetcher interface { - HeaderByHash(ctx context.Context, block common.Hash) (*types.Header, error) + L1BlockRefByHash(ctx context.Context, block common.Hash) (eth.L1BlockRef, error) } type L1HeadBlockNumEnricher struct { @@ -25,10 +25,10 @@ func NewL1HeadBlockNumEnricher(client BlockFetcher) *L1HeadBlockNumEnricher { } func (e *L1HeadBlockNumEnricher) Enrich(ctx context.Context, _ rpcblock.Block, _ GameCaller, game *monTypes.EnrichedGameData) error { - header, err := e.client.HeaderByHash(ctx, game.L1Head) + header, err := e.client.L1BlockRefByHash(ctx, game.L1Head) if err != nil { return fmt.Errorf("failed to retrieve header for L1 head block %v: %w", game.L1Head, err) } - game.L1HeadNum = header.Number.Uint64() + game.L1HeadNum = header.Number return nil } diff --git a/op-dispute-mon/mon/extract/head_enricher_test.go b/op-dispute-mon/mon/extract/head_enricher_test.go index c0cb03b86b7..3c54c09516a 100644 --- a/op-dispute-mon/mon/extract/head_enricher_test.go +++ b/op-dispute-mon/mon/extract/head_enricher_test.go @@ -3,13 +3,12 @@ package extract import ( "context" "errors" - "math/big" "testing" "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" - gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" ) @@ -39,11 +38,11 @@ type stubBlockFetcher struct { err error } -func (s *stubBlockFetcher) HeaderByHash(_ context.Context, _ common.Hash) (*gethTypes.Header, error) { +func (s *stubBlockFetcher) L1BlockRefByHash(_ context.Context, _ common.Hash) (eth.L1BlockRef, error) { if s.err != nil { - return nil, s.err + return eth.L1BlockRef{}, s.err } - return &gethTypes.Header{ - Number: new(big.Int).SetUint64(s.num), + return eth.L1BlockRef{ + Number: s.num, }, nil } diff --git a/op-dispute-mon/mon/monitor.go b/op-dispute-mon/mon/monitor.go index 5f7764adccb..3fb14525e24 100644 --- a/op-dispute-mon/mon/monitor.go +++ b/op-dispute-mon/mon/monitor.go @@ -3,11 +3,11 @@ package mon import ( "context" "fmt" - "math/big" "time" "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -15,8 +15,7 @@ import ( type ForecastResolution func(games []*types.EnrichedGameData, ignoredCount, failedCount int) type Monitor func(games []*types.EnrichedGameData) -type BlockHashFetcher func(ctx context.Context, number *big.Int) (common.Hash, error) -type BlockNumberFetcher func(ctx context.Context) (uint64, error) +type HeadBlockFetcher func(ctx context.Context) (eth.L1BlockRef, error) type Extract func(ctx context.Context, blockHash common.Hash, minTimestamp uint64) ([]*types.EnrichedGameData, int, int, error) type MonitorMetrics interface { @@ -35,11 +34,10 @@ type gameMonitor struct { gameWindow time.Duration monitorInterval time.Duration - forecast ForecastResolution - monitors []Monitor - extract Extract - fetchBlockHash BlockHashFetcher - fetchBlockNumber BlockNumberFetcher + forecast ForecastResolution + monitors []Monitor + extract Extract + fetchHeadBlock HeadBlockFetcher } func newGameMonitor( @@ -49,40 +47,34 @@ func newGameMonitor( metrics MonitorMetrics, monitorInterval time.Duration, gameWindow time.Duration, - fetchBlockHash BlockHashFetcher, - fetchBlockNumber BlockNumberFetcher, + fetchHeadBlock HeadBlockFetcher, extract Extract, forecast ForecastResolution, monitors ...Monitor) *gameMonitor { return &gameMonitor{ - logger: logger, - clock: cl, - ctx: ctx, - done: make(chan struct{}), - metrics: metrics, - monitorInterval: monitorInterval, - gameWindow: gameWindow, - forecast: forecast, - monitors: monitors, - extract: extract, - fetchBlockNumber: fetchBlockNumber, - fetchBlockHash: fetchBlockHash, + logger: logger, + clock: cl, + ctx: ctx, + done: make(chan struct{}), + metrics: metrics, + monitorInterval: monitorInterval, + gameWindow: gameWindow, + forecast: forecast, + monitors: monitors, + extract: extract, + fetchHeadBlock: fetchHeadBlock, } } func (m *gameMonitor) monitorGames() error { start := m.clock.Now() - blockNumber, err := m.fetchBlockNumber(m.ctx) + headBlock, err := m.fetchHeadBlock(m.ctx) if err != nil { return fmt.Errorf("failed to fetch block number: %w", err) } - m.logger.Debug("Fetched block number", "blockNumber", blockNumber) - blockHash, err := m.fetchBlockHash(context.Background(), new(big.Int).SetUint64(blockNumber)) - if err != nil { - return fmt.Errorf("failed to fetch block hash: %w", err) - } + m.logger.Debug("Fetched current head block", "block", headBlock) minGameTimestamp := clock.MinCheckedTimestamp(m.clock, m.gameWindow) - enrichedGames, ignored, failed, err := m.extract(m.ctx, blockHash, minGameTimestamp) + enrichedGames, ignored, failed, err := m.extract(m.ctx, headBlock.Hash, minGameTimestamp) if err != nil { return fmt.Errorf("failed to load games: %w", err) } @@ -92,7 +84,13 @@ func (m *gameMonitor) monitorGames() error { } timeTaken := m.clock.Since(start) m.metrics.RecordMonitorDuration(timeTaken) - m.logger.Info("Completed monitoring update", "blockNumber", blockNumber, "blockHash", blockHash, "duration", timeTaken, "games", len(enrichedGames), "ignored", ignored, "failed", failed) + m.logger.Info("Completed monitoring update", + "blockNumber", headBlock.Number, + "blockHash", headBlock.Hash, + "duration", timeTaken, + "games", len(enrichedGames), + "ignored", ignored, + "failed", failed) return nil } diff --git a/op-dispute-mon/mon/monitor_test.go b/op-dispute-mon/mon/monitor_test.go index 1181c57b4ec..2161e6af14c 100644 --- a/op-dispute-mon/mon/monitor_test.go +++ b/op-dispute-mon/mon/monitor_test.go @@ -3,7 +3,6 @@ package mon import ( "context" "errors" - "math/big" "testing" "time" @@ -11,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-dispute-mon/metrics" monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -24,21 +24,11 @@ var ( func TestMonitor_MonitorGames(t *testing.T) { t.Parallel() - t.Run("FailedFetchBlocknumber", func(t *testing.T) { + t.Run("FailedFetchHeadBlock", func(t *testing.T) { monitor, _, _, _ := setupMonitorTest(t) boom := errors.New("boom") - monitor.fetchBlockNumber = func(ctx context.Context) (uint64, error) { - return 0, boom - } - err := monitor.monitorGames() - require.ErrorIs(t, err, boom) - }) - - t.Run("FailedFetchBlockHash", func(t *testing.T) { - monitor, _, _, _ := setupMonitorTest(t) - boom := errors.New("boom") - monitor.fetchBlockHash = func(ctx context.Context, number *big.Int) (common.Hash, error) { - return common.Hash{}, boom + monitor.fetchHeadBlock = func(ctx context.Context) (eth.L1BlockRef, error) { + return eth.L1BlockRef{}, boom } err := monitor.monitorGames() require.ErrorIs(t, err, boom) @@ -108,11 +98,8 @@ func newEnrichedGameData(proxy common.Address, timestamp uint64) *monTypes.Enric func setupMonitorTest(t *testing.T) (*gameMonitor, *mockExtractor, *mockForecast, []*mockMonitor) { logger := testlog.Logger(t, log.LvlDebug) - fetchBlockNum := func(ctx context.Context) (uint64, error) { - return 1, nil - } - fetchBlockHash := func(ctx context.Context, number *big.Int) (common.Hash, error) { - return common.Hash{}, nil + fetchHeadBlock := func(ctx context.Context) (eth.L1BlockRef, error) { + return eth.L1BlockRef{Number: 1, Hash: common.Hash{0xaa}}, nil } monitorInterval := 100 * time.Millisecond cl := clock.NewAdvancingClock(10 * time.Millisecond) @@ -122,7 +109,7 @@ func setupMonitorTest(t *testing.T) (*gameMonitor, *mockExtractor, *mockForecast monitor1 := &mockMonitor{} monitor2 := &mockMonitor{} monitor3 := &mockMonitor{} - monitor := newGameMonitor(context.Background(), logger, cl, metrics.NoopMetrics, monitorInterval, 10*time.Second, fetchBlockHash, fetchBlockNum, + monitor := newGameMonitor(context.Background(), logger, cl, metrics.NoopMetrics, monitorInterval, 10*time.Second, fetchHeadBlock, extractor.Extract, forecast.Forecast, monitor1.Check, monitor2.Check, monitor3.Check) return monitor, extractor, forecast, []*mockMonitor{monitor1, monitor2, monitor3} } diff --git a/op-dispute-mon/mon/service.go b/op-dispute-mon/mon/service.go index 083e391b911..c44f082d3a8 100644 --- a/op-dispute-mon/mon/service.go +++ b/op-dispute-mon/mon/service.go @@ -4,13 +4,13 @@ import ( "context" "errors" "fmt" - "math/big" "sync/atomic" + "time" "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/bonds" "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" + rpcclient "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-dispute-mon/config" @@ -47,7 +47,9 @@ type Service struct { withdrawals *WithdrawalMonitor rollupClient *sources.RollupClient - l1Client *ethclient.Client + l1RPC rpcclient.RPC + l1Client *sources.L1Client + l1Caller *batching.MultiCaller pprofService *oppprof.Service metricsSrv *httputil.HTTPServer @@ -120,7 +122,7 @@ func (s *Service) initWithdrawalMonitor() { } func (s *Service) initGameCallerCreator() { - s.game = extract.NewGameCallerCreator(s.metrics, batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize)) + s.game = extract.NewGameCallerCreator(s.metrics, s.l1Caller) } func (s *Service) initExtractor(cfg *config.Config) { @@ -159,10 +161,20 @@ func (s *Service) initOutputRollupClient(ctx context.Context, cfg *config.Config } func (s *Service) initL1Client(ctx context.Context, cfg *config.Config) error { - l1Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, s.logger, cfg.L1EthRpc) + l1RPC, err := dial.DialRPCClientWithTimeout(ctx, dial.DefaultDialTimeout, s.logger, cfg.L1EthRpc) if err != nil { return fmt.Errorf("failed to dial L1: %w", err) } + s.l1RPC = rpcclient.NewBaseRPCClient(l1RPC, rpcclient.WithCallTimeout(30*time.Second)) + s.l1Caller = batching.NewMultiCaller(s.l1RPC, batching.DefaultBatchSize) + // The RPC is trusted because the majority of data comes from contract calls which are not verified even when the + // RPC is untrusted and also avoids needing to update op-dispute-mon for L1 hard forks that change the header. + // Note that receipts are never fetched so the RPCKind has no actual effect. + clCfg := sources.L1ClientSimpleConfig(true, sources.RPCKindAny, 100) + l1Client, err := sources.NewL1Client(s.l1RPC, s.logger, s.metrics, clCfg) + if err != nil { + return fmt.Errorf("failed to init l1 client: %w", err) + } s.l1Client = l1Client return nil } @@ -203,24 +215,18 @@ func (s *Service) initMetricsServer(cfg *opmetrics.CLIConfig) error { } func (s *Service) initFactoryContract(cfg *config.Config) error { - factoryContract := contracts.NewDisputeGameFactoryContract(s.metrics, cfg.GameFactoryAddress, - batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize)) + factoryContract := contracts.NewDisputeGameFactoryContract(s.metrics, cfg.GameFactoryAddress, s.l1Caller) s.factoryContract = factoryContract return nil } func (s *Service) initMonitor(ctx context.Context, cfg *config.Config) { - blockHashFetcher := func(ctx context.Context, blockNumber *big.Int) (common.Hash, error) { - block, err := s.l1Client.BlockByNumber(ctx, blockNumber) - if err != nil { - return common.Hash{}, fmt.Errorf("failed to fetch block by number: %w", err) - } - return block.Hash(), nil + headBlockFetcher := func(ctx context.Context) (eth.L1BlockRef, error) { + return s.l1Client.L1BlockRefByLabel(ctx, "latest") } l2ChallengesMonitor := NewL2ChallengesMonitor(s.logger, s.metrics) updateTimeMonitor := NewUpdateTimeMonitor(s.cl, s.metrics) - s.monitor = newGameMonitor(ctx, s.logger, s.cl, s.metrics, cfg.MonitorInterval, cfg.GameWindow, blockHashFetcher, - s.l1Client.BlockNumber, + s.monitor = newGameMonitor(ctx, s.logger, s.cl, s.metrics, cfg.MonitorInterval, cfg.GameWindow, headBlockFetcher, s.extractor.Extract, s.forecast.Forecast, s.bonds.CheckBonds, From 915a1a32cf17d3ba9eef6a1954e4ba6211085acc Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 25 Nov 2024 22:04:21 -0700 Subject: [PATCH 33/61] op-e2e: Build the op-program client upfront (#13095) Now that multiple test processes are running at once, multiple threads are compiling the op-program client in the tests. This PR builds the client upfront to avoid this condition. --- .circleci/config.yml | 4 ++++ op-e2e/system/proofs/build_helper.go | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0368861be01..1ca140e060b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -898,6 +898,10 @@ jobs: - checkout - attach_workspace: at: "." + - run: + name: build op-program-client + command: make op-program-client + working_directory: op-program - run: name: run tests no_output_timeout: <> diff --git a/op-e2e/system/proofs/build_helper.go b/op-e2e/system/proofs/build_helper.go index 42201279867..9bad76b9dcb 100644 --- a/op-e2e/system/proofs/build_helper.go +++ b/op-e2e/system/proofs/build_helper.go @@ -2,7 +2,9 @@ package proofs import ( "context" + "os" "os/exec" + "path/filepath" "strings" "testing" "time" @@ -12,6 +14,15 @@ import ( // BuildOpProgramClient builds the `op-program` client executable and returns the path to the resulting executable func BuildOpProgramClient(t *testing.T) string { + clientPath, err := filepath.Abs("../../../op-program/bin/op-program-client") + require.NoError(t, err) + + _, err = os.Stat(clientPath) + if err == nil { + return clientPath + } + require.ErrorIs(t, err, os.ErrNotExist) + t.Log("Building op-program-client") ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() From f25db964bd90116acc3c628f7b93c9359bf5edee Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Mon, 25 Nov 2024 23:04:44 -0700 Subject: [PATCH 34/61] ci: bump no output timeout (#13096) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1ca140e060b..9d76db1d4ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -884,7 +884,7 @@ jobs: no_output_timeout: description: Timeout for running tests type: string - default: 5m + default: 10m environment_overrides: description: Environment overrides type: string From 77d35a51ea0a0dc0caa50c9efb79ec2eae4bd094 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 26 Nov 2024 04:44:31 -0700 Subject: [PATCH 35/61] op-batcher: Don't log DA post failures on context cancel (#13089) This was causing flakes. --- op-batcher/batcher/driver.go | 6 +++++- op-e2e/system/altda/concurrent_test.go | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 08cf867aed4..93c1425c58b 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -782,7 +782,11 @@ func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[t // So we prefer to mimic the behavior of txmgr and cancel all pending DA/txmgr requests when the batcher is stopped. comm, err := l.AltDA.SetInput(l.shutdownCtx, txdata.CallData()) if err != nil { - l.Log.Error("Failed to post input to Alt DA", "error", err) + // Don't log context cancelled events because they are expected, + // and can happen after tests complete which causes a panic. + if !errors.Is(err, context.Canceled) { + l.Log.Error("Failed to post input to Alt DA", "error", err) + } // requeue frame if we fail to post to the DA Provider so it can be retried // note: this assumes that the da server caches requests, otherwise it might lead to resubmissions of the blobs l.recordFailedDARequest(txdata.ID(), err) diff --git a/op-e2e/system/altda/concurrent_test.go b/op-e2e/system/altda/concurrent_test.go index 32506e5c4a1..e53c7f0f811 100644 --- a/op-e2e/system/altda/concurrent_test.go +++ b/op-e2e/system/altda/concurrent_test.go @@ -34,7 +34,9 @@ func TestBatcherConcurrentAltDARequests(t *testing.T) { cfg.DisableBatcher = true sys, err := cfg.Start(t) require.NoError(t, err, "Error starting up system") - defer sys.Close() + t.Cleanup(func() { + sys.Close() + }) // make every request take 5 seconds, such that only concurrent requests will be able to make progress fast enough sys.FakeAltDAServer.SetPutRequestLatency(5 * time.Second) From 75a367fc44e296db8db6d013e5b2ec8ca3c31315 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 26 Nov 2024 04:57:54 -0700 Subject: [PATCH 36/61] op-node: Noop RemovePeer when closing (#13091) Sometimes, disconnection events happen after the sync client is closed. This can (among other things) lead to panics in tests due to logs occurring after the test has exited. This PR makes RemovePeer a noop when `s.closingPeers == true`, which is the same functionality as `AddPeer`. --- op-node/p2p/sync.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/op-node/p2p/sync.go b/op-node/p2p/sync.go index c8777fe51f9..1b2cc570a2e 100644 --- a/op-node/p2p/sync.go +++ b/op-node/p2p/sync.go @@ -346,6 +346,9 @@ func (s *SyncClient) AddPeer(id peer.ID) { func (s *SyncClient) RemovePeer(id peer.ID) { s.peersLock.Lock() defer s.peersLock.Unlock() + if s.closingPeers { + return + } cancel, ok := s.peers[id] if !ok { s.log.Warn("cannot remove peer from sync duties, peer was not registered", "peer", id) From b707cd8ea9cb7f7b3571131584f81c79db02c336 Mon Sep 17 00:00:00 2001 From: George Knee Date: Tue, 26 Nov 2024 11:59:58 +0000 Subject: [PATCH 37/61] Update dependency on superchain-registry to bring in Unichain Sepolia `holocene_time` (#13098) * update superchain-registry dependency brings in the unichain sepolia holocene_time * update dependency on op-geth --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ef2c5bee53e..7ef9af899b0 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241119111730-bee358f6d6e6 + github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241126105717-d31591e83048 github.com/ethereum/go-ethereum v1.14.11 github.com/fsnotify/fsnotify v1.8.0 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb @@ -250,7 +250,7 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101411.2-rc.2 +replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101411.3-rc.1 //replace github.com/ethereum/go-ethereum => ../go-ethereum diff --git a/go.sum b/go.sum index 12ffc499453..2d20e1e8272 100644 --- a/go.sum +++ b/go.sum @@ -187,10 +187,10 @@ github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/u github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101411.2-rc.2 h1:3suWTU9DwBdY8Yy/ZgZLB/yBy3TwpntpkUn61mZgNpY= -github.com/ethereum-optimism/op-geth v1.101411.2-rc.2/go.mod h1:dITJzx1KXsV2KusscsktidEb00blTSyFhalq8CjfsUY= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241119111730-bee358f6d6e6 h1:+AIYWDX7FeWRLnBVqPiwireTacLLGGww1slGyv+YN0o= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241119111730-bee358f6d6e6/go.mod h1:9feO8jcL5OZ1tvRjEfNAHz4Aggvd6373l+ZxmZZAyZs= +github.com/ethereum-optimism/op-geth v1.101411.3-rc.1 h1:iG5pKldU6e3FZaZJEYzG1H3RsTjARRaLF/MmVkb9JhQ= +github.com/ethereum-optimism/op-geth v1.101411.3-rc.1/go.mod h1:zBADVb3+aon0Idb3uEg/1TFpep+Jdkz3ge9SLFDBXOo= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241126105717-d31591e83048 h1:kb220NeqVRRt/XP5JHt3i4zpLsYNCdWMM/0tDnOFk3o= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241126105717-d31591e83048/go.mod h1:9feO8jcL5OZ1tvRjEfNAHz4Aggvd6373l+ZxmZZAyZs= github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= From c898ed148c2ee64a283b30e8454c419277b8dd45 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 26 Nov 2024 09:19:46 -0500 Subject: [PATCH 38/61] feat: remove _allowUpgrade flag from game impl setters in deploy script (#13087) --- .../scripts/deploy/Deploy.s.sol | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 2cbed1c5568..2135b69aaf2 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -456,9 +456,9 @@ contract Deploy is Deployer { _data: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) }); - setAlphabetFaultGameImplementation({ _allowUpgrade: false }); - setFastFaultGameImplementation({ _allowUpgrade: false }); - setCannonFaultGameImplementation({ _allowUpgrade: false }); + setAlphabetFaultGameImplementation(); + setFastFaultGameImplementation(); + setCannonFaultGameImplementation(); transferDisputeGameFactoryOwnership(); transferDelayedWETHOwnership(); @@ -875,7 +875,7 @@ contract Deploy is Deployer { } /// @notice Sets the implementation for the `CANNON` game type in the `DisputeGameFactory` - function setCannonFaultGameImplementation(bool _allowUpgrade) public broadcast { + function setCannonFaultGameImplementation() public broadcast { console.log("Setting Cannon FaultDisputeGame implementation"); IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); @@ -883,7 +883,6 @@ contract Deploy is Deployer { // Set the Cannon FaultDisputeGame implementation in the factory. _setFaultGameImplementation({ _factory: factory, - _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, @@ -897,7 +896,7 @@ contract Deploy is Deployer { } /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory` - function setAlphabetFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { + function setAlphabetFaultGameImplementation() public onlyDevnet broadcast { console.log("Setting Alphabet FaultDisputeGame implementation"); IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); @@ -905,7 +904,6 @@ contract Deploy is Deployer { Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); _setFaultGameImplementation({ _factory: factory, - _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, @@ -920,7 +918,7 @@ contract Deploy is Deployer { } /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory` - function setFastFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { + function setFastFaultGameImplementation() public onlyDevnet broadcast { console.log("Setting Fast FaultDisputeGame implementation"); IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); @@ -939,7 +937,6 @@ contract Deploy is Deployer { ); _setFaultGameImplementation({ _factory: factory, - _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, @@ -956,12 +953,11 @@ contract Deploy is Deployer { /// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`. function _setFaultGameImplementation( IDisputeGameFactory _factory, - bool _allowUpgrade, FaultDisputeGameParams memory _params ) internal { - if (address(_factory.gameImpls(_params.gameType)) != address(0) && !_allowUpgrade) { + if (address(_factory.gameImpls(_params.gameType)) != address(0)) { console.log( "[WARN] DisputeGameFactoryProxy: `FaultDisputeGame` implementation already set for game type: %s", vm.toString(GameType.unwrap(_params.gameType)) From f633e8568fff16430d54871c84ad74b9242c0704 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 26 Nov 2024 10:54:07 -0500 Subject: [PATCH 39/61] feat: remove unused onlyTestnetOrDevnet modifier (#13086) --- .../contracts-bedrock/scripts/deploy/Deploy.s.sol | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 2135b69aaf2..9e688f29ae6 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -97,18 +97,6 @@ contract Deploy is Deployer { } } - /// @notice Modifier that will only allow a function to be called on a public - /// testnet or devnet. - modifier onlyTestnetOrDevnet() { - uint256 chainid = block.chainid; - if ( - chainid == Chains.Goerli || chainid == Chains.Sepolia || chainid == Chains.LocalDevnet - || chainid == Chains.GethDevnet - ) { - _; - } - } - /// @notice Modifier that wraps a function with statediff recording. /// The returned AccountAccess[] array is then written to /// the `snapshots/state-diff/.json` output file. From 7726c1aa49de661e13d73dcbcb5218b6af110df5 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 27 Nov 2024 01:57:38 +1000 Subject: [PATCH 40/61] op-deployer: Simplify and fix bootstrap disputegame (#13094) * op-deployer: Load CLI options into the bootstrap disputegame config * op-deployer: Simplify bootstrap disputegame to only deploy the disputegame contract --- .../pkg/deployer/bootstrap/delayed_weth.go | 21 ++- .../deployer/bootstrap/delayed_weth_test.go | 45 ++++++ .../pkg/deployer/bootstrap/dispute_game.go | 74 ++++++++-- .../deployer/bootstrap/dispute_game_test.go | 66 +++++++++ op-deployer/pkg/deployer/bootstrap/flags.go | 8 +- op-deployer/pkg/deployer/opcm/dispute_game.go | 8 +- .../pkg/deployer/opcm/dispute_game_test.go | 15 +- .../scripts/deploy/DeployDisputeGame.s.sol | 138 ++---------------- 8 files changed, 217 insertions(+), 158 deletions(-) create mode 100644 op-deployer/pkg/deployer/bootstrap/delayed_weth_test.go create mode 100644 op-deployer/pkg/deployer/bootstrap/dispute_game_test.go diff --git a/op-deployer/pkg/deployer/bootstrap/delayed_weth.go b/op-deployer/pkg/deployer/bootstrap/delayed_weth.go index 451b0741f24..67b1b66760a 100644 --- a/op-deployer/pkg/deployer/bootstrap/delayed_weth.go +++ b/op-deployer/pkg/deployer/bootstrap/delayed_weth.go @@ -69,22 +69,31 @@ func DelayedWETHCLI(cliCtx *cli.Context) error { l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) oplog.SetGlobalLogHandler(l.Handler()) + config, err := NewDelayedWETHConfigFromClI(cliCtx, l) + if err != nil { + return err + } + + ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) + + return DelayedWETH(ctx, config) +} + +func NewDelayedWETHConfigFromClI(cliCtx *cli.Context, l log.Logger) (DelayedWETHConfig, error) { l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName) privateKey := cliCtx.String(deployer.PrivateKeyFlagName) artifactsURLStr := cliCtx.String(ArtifactsLocatorFlagName) artifactsLocator := new(artifacts2.Locator) if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil { - return fmt.Errorf("failed to parse artifacts URL: %w", err) + return DelayedWETHConfig{}, fmt.Errorf("failed to parse artifacts URL: %w", err) } - - ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) - - return DelayedWETH(ctx, DelayedWETHConfig{ + config := DelayedWETHConfig{ L1RPCUrl: l1RPCUrl, PrivateKey: privateKey, Logger: l, ArtifactsLocator: artifactsLocator, - }) + } + return config, nil } func DelayedWETH(ctx context.Context, cfg DelayedWETHConfig) error { diff --git a/op-deployer/pkg/deployer/bootstrap/delayed_weth_test.go b/op-deployer/pkg/deployer/bootstrap/delayed_weth_test.go new file mode 100644 index 00000000000..5e3b667b9b2 --- /dev/null +++ b/op-deployer/pkg/deployer/bootstrap/delayed_weth_test.go @@ -0,0 +1,45 @@ +package bootstrap + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" +) + +func TestNewDelayedWETHConfigFromCLI(t *testing.T) { + ctx, err := parseCLIArgs(DelayedWETHFlags, + "--artifacts-locator", "tag://op-contracts/v1.6.0", + "--l1-rpc-url", "http://foo", + "--private-key", "0x123456") + require.NoError(t, err) + + logger := testlog.Logger(t, log.LvlInfo) + cfg, err := NewDelayedWETHConfigFromClI(ctx, logger) + require.NoError(t, err) + require.Same(t, logger, cfg.Logger) + require.Equal(t, "op-contracts/v1.6.0", cfg.ArtifactsLocator.Tag) + require.True(t, cfg.ArtifactsLocator.IsTag()) + require.Equal(t, "0x123456", cfg.PrivateKey) +} + +func parseCLIArgs(flags []cli.Flag, args ...string) (*cli.Context, error) { + app := cli.NewApp() + app.Flags = cliapp.ProtectFlags(flags) + var ctx *cli.Context + app.Action = func(c *cli.Context) error { + ctx = c + return nil + } + argsWithCmd := make([]string, len(args)+1) + argsWithCmd[0] = "bootstrap" + copy(argsWithCmd[1:], args) + err := app.Run(argsWithCmd) + if err != nil { + return nil, err + } + return ctx, nil +} diff --git a/op-deployer/pkg/deployer/bootstrap/dispute_game.go b/op-deployer/pkg/deployer/bootstrap/dispute_game.go index d3efe36f9ca..f33f5106053 100644 --- a/op-deployer/pkg/deployer/bootstrap/dispute_game.go +++ b/op-deployer/pkg/deployer/bootstrap/dispute_game.go @@ -7,6 +7,9 @@ import ( "strings" artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" + "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/snapshots" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimism/op-deployer/pkg/env" @@ -36,9 +39,7 @@ type DisputeGameConfig struct { privateKeyECDSA *ecdsa.PrivateKey - MinProposalSizeBytes uint64 - ChallengePeriodSeconds uint64 - MipsVersion uint64 + Vm common.Address GameKind string GameType uint32 AbsolutePrestate common.Hash @@ -84,22 +85,44 @@ func DisputeGameCLI(cliCtx *cli.Context) error { l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) oplog.SetGlobalLogHandler(l.Handler()) + cfg, err := NewDisputeGameConfigFromCLI(cliCtx, l) + if err != nil { + return err + } + ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) + return DisputeGame(ctx, cfg) +} + +func NewDisputeGameConfigFromCLI(cliCtx *cli.Context, l log.Logger) (DisputeGameConfig, error) { l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName) privateKey := cliCtx.String(deployer.PrivateKeyFlagName) artifactsURLStr := cliCtx.String(ArtifactsLocatorFlagName) artifactsLocator := new(artifacts2.Locator) if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil { - return fmt.Errorf("failed to parse artifacts URL: %w", err) + return DisputeGameConfig{}, fmt.Errorf("failed to parse artifacts URL: %w", err) } - ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) - - return DisputeGame(ctx, DisputeGameConfig{ + cfg := DisputeGameConfig{ L1RPCUrl: l1RPCUrl, PrivateKey: privateKey, Logger: l, ArtifactsLocator: artifactsLocator, - }) + + Vm: common.HexToAddress(cliCtx.String(VmFlagName)), + GameKind: cliCtx.String(GameKindFlagName), + GameType: uint32(cliCtx.Uint64(GameTypeFlagName)), + AbsolutePrestate: common.HexToHash(cliCtx.String(AbsolutePrestateFlagName)), + MaxGameDepth: cliCtx.Uint64(MaxGameDepthFlagName), + SplitDepth: cliCtx.Uint64(SplitDepthFlagName), + ClockExtension: cliCtx.Uint64(ClockExtensionFlagName), + MaxClockDuration: cliCtx.Uint64(MaxClockDurationFlagName), + DelayedWethProxy: common.HexToAddress(cliCtx.String(DelayedWethProxyFlagName)), + AnchorStateRegistryProxy: common.HexToAddress(cliCtx.String(AnchorStateRegistryProxyFlagName)), + L2ChainId: cliCtx.Uint64(L2ChainIdFlagName), + Proposer: common.HexToAddress(cliCtx.String(ProposerFlagName)), + Challenger: common.HexToAddress(cliCtx.String(ChallengerFlagName)), + } + return cfg, nil } func DisputeGame(ctx context.Context, cfg DisputeGameConfig) error { @@ -175,6 +198,25 @@ func DisputeGame(ctx context.Context, cfg DisputeGameConfig) error { release = "dev" } + // We need to etch the VM and PreimageOracle addresses so that they have nonzero code + // and the checks in the FaultDisputeGame constructor pass. + oracleAddr, err := loadOracleAddr(ctx, l1Client, cfg.Vm) + if err != nil { + return err + } + addresses := []common.Address{ + cfg.Vm, + oracleAddr, + } + for _, addr := range addresses { + code, err := l1Client.CodeAt(ctx, addr, nil) + if err != nil { + return fmt.Errorf("failed to get code for %v: %w", addr, err) + } + host.ImportAccount(addr, types.Account{ + Code: code, + }) + } lgr.Info("deploying dispute game", "release", release) dgo, err := opcm.DeployDisputeGame( @@ -182,9 +224,7 @@ func DisputeGame(ctx context.Context, cfg DisputeGameConfig) error { opcm.DeployDisputeGameInput{ Release: release, StandardVersionsToml: standardVersionsTOML, - MipsVersion: cfg.MipsVersion, - MinProposalSizeBytes: cfg.MinProposalSizeBytes, - ChallengePeriodSeconds: cfg.ChallengePeriodSeconds, + VmAddress: cfg.Vm, GameKind: cfg.GameKind, GameType: cfg.GameType, AbsolutePrestate: cfg.AbsolutePrestate, @@ -214,3 +254,15 @@ func DisputeGame(ctx context.Context, cfg DisputeGameConfig) error { } return nil } + +func loadOracleAddr(ctx context.Context, l1Client *ethclient.Client, vmAddr common.Address) (common.Address, error) { + callData, err := snapshots.LoadMIPSABI().Pack("oracle") + if err != nil { + return common.Address{}, fmt.Errorf("failed to create vm.oracle() calldata: %w", err) + } + result, err := l1Client.CallContract(ctx, ethereum.CallMsg{Data: callData, To: &vmAddr}, nil) + if err != nil { + return common.Address{}, fmt.Errorf("failed to call vm.oracle(): %w", err) + } + return common.BytesToAddress(result), nil +} diff --git a/op-deployer/pkg/deployer/bootstrap/dispute_game_test.go b/op-deployer/pkg/deployer/bootstrap/dispute_game_test.go new file mode 100644 index 00000000000..e24ae3754df --- /dev/null +++ b/op-deployer/pkg/deployer/bootstrap/dispute_game_test.go @@ -0,0 +1,66 @@ +package bootstrap + +import ( + "reflect" + "testing" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestNewDisputeGameConfigFromCLI(t *testing.T) { + ctx, err := parseCLIArgs(DisputeGameFlags, + "--artifacts-locator", "tag://op-contracts/v1.6.0", + "--l1-rpc-url", "http://foo", + "--private-key", "0x123456", + + "--game-type", "2", + "--delayed-weth-proxy", common.Address{0xaa}.Hex(), + "--anchor-state-registry-proxy", common.Address{0xbb}.Hex(), + "--l2-chain-id", "901", + "--proposer", common.Address{0xcc}.Hex(), + "--challenger", common.Address{0xdd}.Hex(), + "--vm", common.Address{0xee}.Hex(), + ) + require.NoError(t, err) + + logger := testlog.Logger(t, log.LvlInfo) + cfg, err := NewDisputeGameConfigFromCLI(ctx, logger) + require.NoError(t, err) + require.Same(t, logger, cfg.Logger) + require.Equal(t, "op-contracts/v1.6.0", cfg.ArtifactsLocator.Tag) + require.True(t, cfg.ArtifactsLocator.IsTag()) + require.Equal(t, "0x123456", cfg.PrivateKey) + require.Equal(t, "FaultDisputeGame", cfg.GameKind) + require.Equal(t, uint32(2), cfg.GameType) + require.Equal(t, standard.DisputeAbsolutePrestate, cfg.AbsolutePrestate) + require.Equal(t, standard.DisputeMaxGameDepth, cfg.MaxGameDepth) + require.Equal(t, standard.DisputeSplitDepth, cfg.SplitDepth) + require.Equal(t, standard.DisputeClockExtension, cfg.ClockExtension) + require.Equal(t, standard.DisputeMaxClockDuration, cfg.MaxClockDuration) + require.Equal(t, common.Address{0xaa}, cfg.DelayedWethProxy) + require.Equal(t, common.Address{0xbb}, cfg.AnchorStateRegistryProxy) + require.Equal(t, common.Address{0xcc}, cfg.Proposer) + require.Equal(t, common.Address{0xdd}, cfg.Challenger) + require.Equal(t, common.Address{0xee}, cfg.Vm) + require.Equal(t, uint64(901), cfg.L2ChainId) + + // Check all fields are set to ensure any newly added fields don't get missed. + cfgRef := reflect.ValueOf(cfg) + cfgType := reflect.TypeOf(cfg) + var unsetFields []string + for i := 0; i < cfgRef.NumField(); i++ { + field := cfgType.Field(i) + if field.Type == reflect.TypeOf(cfg.privateKeyECDSA) { + // privateKeyECDSA is only set when Check() is called so skip it. + continue + } + if cfgRef.Field(i).IsZero() { + unsetFields = append(unsetFields, field.Name) + } + } + require.Empty(t, unsetFields, "Found unset fields in config") +} diff --git a/op-deployer/pkg/deployer/bootstrap/flags.go b/op-deployer/pkg/deployer/bootstrap/flags.go index 73f99e7b432..b35e96a5f6a 100644 --- a/op-deployer/pkg/deployer/bootstrap/flags.go +++ b/op-deployer/pkg/deployer/bootstrap/flags.go @@ -16,6 +16,7 @@ const ( ProofMaturityDelaySecondsFlagName = "proof-maturity-delay-seconds" DisputeGameFinalityDelaySecondsFlagName = "dispute-game-finality-delay-seconds" MIPSVersionFlagName = "mips-version" + VmFlagName = "vm" GameKindFlagName = "game-kind" GameTypeFlagName = "game-type" AbsolutePrestateFlagName = "absolute-prestate" @@ -73,6 +74,11 @@ var ( EnvVars: deployer.PrefixEnvVar("MIPS_VERSION"), Value: standard.MIPSVersion, } + VmFlag = &cli.StringFlag{ + Name: VmFlagName, + Usage: "VM contract address.", + EnvVars: deployer.PrefixEnvVar("VM"), + } GameKindFlag = &cli.StringFlag{ Name: GameKindFlagName, Usage: "Game kind (FaultDisputeGame or PermissionedDisputeGame).", @@ -173,7 +179,7 @@ var DisputeGameFlags = []cli.Flag{ ArtifactsLocatorFlag, MinProposalSizeBytesFlag, ChallengePeriodSecondsFlag, - MIPSVersionFlag, + VmFlag, GameKindFlag, GameTypeFlag, AbsolutePrestateFlag, diff --git a/op-deployer/pkg/deployer/opcm/dispute_game.go b/op-deployer/pkg/deployer/opcm/dispute_game.go index 0e117c040d8..481a401d07d 100644 --- a/op-deployer/pkg/deployer/opcm/dispute_game.go +++ b/op-deployer/pkg/deployer/opcm/dispute_game.go @@ -11,9 +11,7 @@ import ( type DeployDisputeGameInput struct { Release string StandardVersionsToml string - MipsVersion uint64 - MinProposalSizeBytes uint64 - ChallengePeriodSeconds uint64 + VmAddress common.Address GameKind string GameType uint32 AbsolutePrestate common.Hash @@ -33,9 +31,7 @@ func (input *DeployDisputeGameInput) InputSet() bool { } type DeployDisputeGameOutput struct { - DisputeGameImpl common.Address - MipsSingleton common.Address - PreimageOracleSingleton common.Address + DisputeGameImpl common.Address } func (output *DeployDisputeGameOutput) CheckOutput(input common.Address) error { diff --git a/op-deployer/pkg/deployer/opcm/dispute_game_test.go b/op-deployer/pkg/deployer/opcm/dispute_game_test.go index f39849be440..2b2d33f9efe 100644 --- a/op-deployer/pkg/deployer/opcm/dispute_game_test.go +++ b/op-deployer/pkg/deployer/opcm/dispute_game_test.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-deployer/pkg/env" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) @@ -26,13 +27,15 @@ func TestDeployDisputeGame(t *testing.T) { standardVersionsTOML, err := standard.L1VersionsDataFor(11155111) require.NoError(t, err) + vmAddr := common.Address{'V'} + host.ImportAccount(vmAddr, types.Account{Code: vmCode}) + // Address has to match the one returned by vmCode for oracle()(address) + host.ImportAccount(common.HexToAddress("0x92240135b46fc1142dA181f550aE8f595B858854"), types.Account{Code: oracleCode}) input := DeployDisputeGameInput{ Release: "dev", StandardVersionsToml: standardVersionsTOML, - MipsVersion: 1, - MinProposalSizeBytes: standard.MinProposalSizeBytes, - ChallengePeriodSeconds: standard.ChallengePeriodSeconds, + VmAddress: vmAddr, GameKind: "PermissionedDisputeGame", GameType: 1, AbsolutePrestate: common.Hash{'A'}, @@ -51,6 +54,8 @@ func TestDeployDisputeGame(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, output.DisputeGameImpl) - require.NotEmpty(t, output.MipsSingleton) - require.NotEmpty(t, output.PreimageOracleSingleton) } + +// Code to etch so that the VM oracle() method and the oracle challengePeriod() methods work (they return immutables) +var vmCode = common.FromHex("0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600c81526020017f312e322e312d626574612e37000000000000000000000000000000000000000081525081565b60405161008f919061269c565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000092240135b46fc1142da181f550ae8f595b85885416815260200161008f565b6100ef6100ea366004612751565b6100fd565b60405190815260200161008f565b6000610107612612565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e57610246610408565b9150506103ff565b6101408101805160010167ffffffffffffffff16905260006101a4905060008060006102838560600151866000015186610559565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610583565b955050505050506103ff565b63ffffffff8216603014806102da575063ffffffff82166038145b156102ea576102b385848461095d565b6000610364866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6040805160e0810182528281526101608901516020820152885191810191909152610524606082015263ffffffff808716608083015285811660a0830152841660c08201529091506103b581610b78565b50508752815163ffffffff9081166060808a01919091526020840151821660808a01526040840151821660a08a01528301511660c08801526103f5610408565b9750505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a84015260009261020092909160628301919060018111156104b5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b60208110156104dc57601c86015184526020909501946004909301926001016104b8565b506000835283830384a06000945080600181146104fc5760039550610524565b828015610514576001811461051d5760029650610522565b60009650610522565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610569858786611001565b925050603f601a83901c8116915082165b93509350939050565b600061058d612612565b608090506000806000806105c48561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff1603610609576105f485858960e00151611053565b63ffffffff1660e08a0152909250905061086c565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff871601610642576340000000915061086c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff871601610678576001915061086c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff8716016106cc57600161012088015260ff85166101008801526106bf610408565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107ca5760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f00000000000000000000000092240135b46fc1142da181f550ae8f595b85885473ffffffffffffffffffffffffffffffffffffffff16815260200161079a6101a4600160ff16610380020190565b8152895160209091015290506107af816110e7565b50508b5263ffffffff1660408b0152909350915061086c9050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff87160161082f5760208701516040880151610815918791879187916105248d51611367565b63ffffffff1660408b015260208a0152909250905061086c565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff87160161086c57610866858561145d565b90925090505b60006108e6886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a0152905061094f610408565b9a9950505050505050505050565b610160830151600090601f601585901c169082908260208110610982576109826127c5565b60200201519050601f601086901c16600061099c8761159c565b905082810163fffffffc166000610524905060006109bf8b600001518484611001565b905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd063ffffffff8b16016109f7575080610a93565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc863ffffffff8b1601610a615760008c61016001518763ffffffff1660208110610a4357610a436127c5565b60200201519050610a558585836115b3565b8d525060019050610a93565b6040517fecf79d0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b0d8d6040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b9050610b22818e610160015189856001611655565b610b5f8d82805163ffffffff9081166060808501919091526020830151821660808501526040830151821660a0850152909101511660c090910152565b610b67610408565b9d9c50505050505050505050505050565b604081015160a0820151600090819063ffffffff1660021480610ba557508360a0015163ffffffff166003145b15610bfe57608084015184516020808201519087015160a088015163f0000000909216630ffffffc600295861b161793610bf8939263ffffffff1614610bec57601f610bef565b60005b60ff168461172a565b50610ffa565b60808401516020808601516000928392601f601083901c8116939260151c16908110610c2c57610c2c6127c5565b602002015160a0880151909350819063ffffffff161580610c5757508760a0015163ffffffff16601c145b15610c985787602001518263ffffffff1660208110610c7857610c786127c5565b60200201519250600b886080015163ffffffff16901c601f169050610d77565b60208860a0015163ffffffff161015610d12578760a0015163ffffffff16600c1480610cce57508760a0015163ffffffff16600d145b80610ce357508760a0015163ffffffff16600e145b15610cf857876080015161ffff169250610d77565b610d0b886080015161ffff1660106117fd565b9250610d77565b60288860a0015163ffffffff16101580610d3657508760a0015163ffffffff166022145b80610d4b57508760a0015163ffffffff166026145b15610d775787602001518263ffffffff1660208110610d6c57610d6c6127c5565b602002015192508190505b60048860a0015163ffffffff1610158015610d9c575060088860a0015163ffffffff16105b80610db157508760a0015163ffffffff166001145b15610ddd57610dd4886000015189602001518a60a001518b608001518689611870565b50505050610ffa565b600063ffffffff9050600060208a60a0015163ffffffff1610610e4d57610e0d8a6080015161ffff1660106117fd565b8601955060008663fffffffc169050610e2f8b60400151828d60600151611001565b915060288b60a0015163ffffffff1610610e4b57809250600093505b505b6000610e698b608001518c60a001518d60c001518a8a87611ab3565b63ffffffff1690508a60a0015163ffffffff166000148015610e96575060088b60c0015163ffffffff1610155b8015610eac5750601c8b60c0015163ffffffff16105b15610fb2578a60c0015163ffffffff1660081480610ed457508a60c0015163ffffffff166009145b15610f1357610f078b600001518c602001518d60c0015163ffffffff16600814610efe5786610f01565b60005b8a61172a565b50505050505050610ffa565b8a60c0015163ffffffff16600a03610f40578a5160208c0151610f079190868a63ffffffff8b1615611655565b8a60c0015163ffffffff16600b03610f6e578a5160208c0151610f079190868a63ffffffff8b161515611655565b60108b60c0015163ffffffff1610158015610f935750601c8b60c0015163ffffffff16105b15610fb257610f078b600001518c602001518d60c001518a8a89612121565b8263ffffffff1663ffffffff14610fdc57610fd2838c60600151836115b3565b9950600198508297505b610ff28b600001518c6020015186846001611655565b505050505050505b9193909250565b60008061100f8585856123da565b90925090508061104b576040517f8e77b2b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b6000808284610fff81161561106d57610fff811661100003015b8663ffffffff166000036110d95784935090810190636000000063ffffffff831611806110a557508463ffffffff168263ffffffff16105b806110bb57508563ffffffff168163ffffffff16105b156110d4575063ffffffff92506016915083905061057a565b6110dd565b8693505b5093509350939050565b610100810151608082015182516000928392918390819063ffffffff161561135e57865163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611318576000876020015163fffffffc169050600061115c896101000151838b60e00151611001565b60608a015190915060001a6001036111de576111d889606001518a60a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608a01525b6000808a60c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e18c606001518d608001516040518363ffffffff1660e01b815260040161123792919091825263ffffffff16602082015260400190565b6040805180830381865afa158015611253573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127791906127f4565b60208d015160408e0151929450909250906003821660048190038481101561129d578094505b50838210156112aa578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b039150811981169050858119881617965050506112fe868e60e00151876115b3565b929b5050509689019695506001945091925061135e915050565b865163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd01611352578660400151955061135e565b63ffffffff9550600994505b91939550919395565b600080858563ffffffff8b1660011480611387575063ffffffff8b166002145b80611398575063ffffffff8b166004145b156113a55788935061144f565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c16016114435760006113e5868c63fffffffc1689611001565b90508860038c166004038b8110156113fb57809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b1791506000905061144f565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166001036114f95763ffffffff84161580611487575063ffffffff84166001145b80611498575063ffffffff84166002145b806114a9575063ffffffff84166005145b806114ba575063ffffffff84166003145b806114cb575063ffffffff84166006145b806114dc575063ffffffff84166004145b156114ea5760009150611595565b5063ffffffff90506009611595565b8263ffffffff1660030361158a5763ffffffff84161580611520575063ffffffff84166005145b80611531575063ffffffff84166003145b1561153f5760009150611595565b63ffffffff84166001148061155a575063ffffffff84166002145b8061156b575063ffffffff84166006145b8061157c575063ffffffff84166004145b156114ea5760019150611595565b5063ffffffff905060165b9250929050565b60006115ad8261ffff1660106117fd565b92915050565b60006115be83612485565b60038416156115cc57600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b81101561164a5760208601953582821c600116801561161a576001811461162f57611640565b60008581526020839052604090209450611640565b600082815260208690526040902094505b50506001016115f2565b509095945050505050565b60208363ffffffff16106116ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064015b60405180910390fd5b63ffffffff8316158015906116dc5750805b1561170b5781848463ffffffff16602081106116fa576116fa6127c5565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b836000015160040163ffffffff16846020015163ffffffff16146117aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064016116c1565b835160208501805163ffffffff90811687528381169091528316156117f65780600801848463ffffffff16602081106117e5576117e56127c5565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261185a57600061185c565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146118f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016116c1565b8463ffffffff166004148061190d57508463ffffffff166005145b15611984576000868463ffffffff166020811061192c5761192c6127c5565b602002015190508063ffffffff168363ffffffff1614801561195457508563ffffffff166004145b8061197c57508063ffffffff168363ffffffff161415801561197c57508563ffffffff166005145b915050611a56565b8463ffffffff166006036119a15760008260030b13159050611a56565b8463ffffffff166007036119bd5760008260030b139050611a56565b8463ffffffff16600103611a5657601f601085901c1660008190036119e65760008360030b1291505b8063ffffffff16601003611a1057875160080163ffffffff166103e08801526000600384900b1291505b8063ffffffff16600103611a295760008360030b121591505b8063ffffffff16601103611a5457875160080163ffffffff166103e08801526000600384900b121591505b505b8651602088015163ffffffff1688528115611a97576002611a7c8661ffff1660106117fd565b63ffffffff90811690911b8201600401166020890152611aa9565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff86161580611ae0575060088663ffffffff1610158015611ae05750600f8663ffffffff16105b15611ee0578560088114611b235760098114611b2c57600a8114611b3557600b8114611b3e57600c8114611b4757600d8114611b5057600e8114611b5957611b5e565b60209550611b5e565b60219550611b5e565b602a9550611b5e565b602b9550611b5e565b60249550611b5e565b60259550611b5e565b602695505b508463ffffffff16600003611b83575063ffffffff8216601f600688901c161b612117565b8463ffffffff16600203611ba7575063ffffffff8216601f600688901c161c612117565b8463ffffffff16600303611bdb57601f600688901c16611bd363ffffffff8516821c60208390036117fd565b915050612117565b8463ffffffff16600403611bfb575063ffffffff8216601f84161b612117565b8463ffffffff16600603611c1b575063ffffffff8216601f84161c612117565b8463ffffffff16600703611c4357601f8416611bd363ffffffff8516821c60208390036117fd565b8463ffffffff16600803611c58575082612117565b8463ffffffff16600903611c6d575082612117565b8463ffffffff16600a03611c82575082612117565b8463ffffffff16600b03611c97575082612117565b8463ffffffff16600c03611cac575082612117565b8463ffffffff16600f03611cc1575082612117565b8463ffffffff16601003611cd6575082612117565b8463ffffffff16601103611ceb575082612117565b8463ffffffff16601203611d00575082612117565b8463ffffffff16601303611d15575082612117565b8463ffffffff16601803611d2a575082612117565b8463ffffffff16601903611d3f575082612117565b8463ffffffff16601a03611d54575082612117565b8463ffffffff16601b03611d69575082612117565b8463ffffffff16602003611d805750828201612117565b8463ffffffff16602103611d975750828201612117565b8463ffffffff16602203611dae5750818303612117565b8463ffffffff16602303611dc55750818303612117565b8463ffffffff16602403611ddc5750828216612117565b8463ffffffff16602503611df35750828217612117565b8463ffffffff16602603611e0a5750828218612117565b8463ffffffff16602703611e22575082821719612117565b8463ffffffff16602a03611e51578260030b8460030b12611e44576000611e47565b60015b60ff169050612117565b8463ffffffff16602b03611e79578263ffffffff168463ffffffff1610611e44576000611e47565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016116c1565b611e79565b8563ffffffff16601c03611f60578463ffffffff16600203611f055750828202612117565b8463ffffffff1660201480611f2057508463ffffffff166021145b15611edb578463ffffffff16602003611f37579219925b60005b6380000000851615611f59576401fffffffe600195861b169401611f3a565b9050612117565b8563ffffffff16600f03611f81575065ffffffff0000601083901b16612117565b8563ffffffff16602003611f9c57611f59848360018061251e565b8563ffffffff16602103611fb857611f5984836002600161251e565b8563ffffffff16602203611fe6575063ffffffff60086003851602811681811b198416918316901b17612117565b8563ffffffff1660230361200257611f5984836004600161251e565b8563ffffffff1660240361201e57611f5984836001600061251e565b8563ffffffff1660250361203a57611f5984836002600061251e565b8563ffffffff1660260361206b575063ffffffff60086003851602601803811681811c198416918316901c17612117565b8563ffffffff1660280361208657611f598483600186612566565b8563ffffffff166029036120a157611f598483600286612566565b8563ffffffff16602a036120cf575063ffffffff60086003851602811681811c198316918416901c17612117565b8563ffffffff16602b036120ea57611f598483600486612566565b8563ffffffff16602e03611e79575063ffffffff60086003851602601803811681811b198316918416901b175b9695505050505050565b60008463ffffffff1660100361213c57506060860151612382565b8463ffffffff1660110361215b5763ffffffff84166060880152612382565b8463ffffffff1660120361217457506040860151612382565b8463ffffffff166013036121935763ffffffff84166040880152612382565b8463ffffffff166018036121c75763ffffffff600385810b9085900b02602081901c821660608a0152166040880152612382565b8463ffffffff166019036121f85763ffffffff84811681851602602081901c821660608a0152166040880152612382565b8463ffffffff16601a036122bb578260030b600003612273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016116c1565b8260030b8460030b8161228857612288612818565b0763ffffffff166060880152600383810b9085900b816122aa576122aa612818565b0563ffffffff166040880152612382565b8463ffffffff16601b03612382578263ffffffff16600003612339576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016116c1565b8263ffffffff168463ffffffff168161235457612354612818565b0663ffffffff90811660608901528381169085168161237557612375612818565b0463ffffffff1660408801525b63ffffffff8216156123b85780868363ffffffff16602081106123a7576123a76127c5565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000806123e683612485565b60038416156123f457600080fd5b6020830192358460051c8160005b601b81101561245a5760208701963583821c600116801561242a576001811461243f57612450565b60008481526020839052604090209350612450565b600082815260208590526040902093505b5050600101612402565b508714925050811561247c57601f8516601c0360031b81901c63ffffffff1692505b50935093915050565b36610380820181101561251a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016116c1565b5050565b60008060008061252e888761259a565b925092509250828263ffffffff168863ffffffff16901c169350841561255b5761255884826117fd565b93505b505050949350505050565b6000806000612575878661259a565b5063ffffffff868316811691811691821b9216901b1987161792505050949350505050565b600080806407fffffff8600385901b16816125b6826020612847565b63ffffffff9081161c905060006125ce600188612847565b198816600316905060006125e3886004612847565b9050888216600060036125f68385612847565b959c63ffffffff909616901b9a50949850929650505050505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810191909152610160810161267861267d565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b818110156126c9578581018301518582016040015282016126ad565b818111156126db576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261272157600080fd5b50813567ffffffffffffffff81111561273957600080fd5b60208301915083602082850101111561159557600080fd5b60008060008060006060868803121561276957600080fd5b853567ffffffffffffffff8082111561278157600080fd5b61278d89838a0161270f565b909750955060208801359150808211156127a657600080fd5b506127b38882890161270f565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561280757600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600063ffffffff8381169083168181101561288b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b03939250505056fea164736f6c634300080f000a") +var oracleCode = common.FromHex("0x6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600581526020017f312e312e3200000000000000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000001ec3061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000001518061024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000001518061151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000001ec308163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a") diff --git a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol index c128260a21d..153e4b65fdb 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployDisputeGame.s.sol @@ -18,8 +18,6 @@ import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDi import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; -import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; -import { IMIPS } from "src/cannon/interfaces/IMIPS.sol"; /// @title DeployDisputeGameInput contract DeployDisputeGameInput is BaseDeployIO { @@ -27,13 +25,6 @@ contract DeployDisputeGameInput is BaseDeployIO { string internal _release; string internal _standardVersionsToml; - // Specify which MIPS version to use. - uint256 internal _mipsVersion; - - // All inputs required to deploy PreimageOracle. - uint256 internal _minProposalSizeBytes; - uint256 internal _challengePeriodSeconds; - // Specify which game kind is being deployed here. string internal _gameKind; @@ -46,6 +37,7 @@ contract DeployDisputeGameInput is BaseDeployIO { uint256 internal _maxClockDuration; IDelayedWETH internal _delayedWethProxy; IAnchorStateRegistry internal _anchorStateRegistryProxy; + IBigStepper internal _vm; uint256 internal _l2ChainId; // Additional inputs required to deploy PermissionedDisputeGame. @@ -53,16 +45,7 @@ contract DeployDisputeGameInput is BaseDeployIO { address internal _challenger; function set(bytes4 _sel, uint256 _value) public { - if (_sel == this.mipsVersion.selector) { - require(_value == 1 || _value == 2, "DeployDisputeGame: unknown mips version"); - _mipsVersion = _value; - } else if (_sel == this.minProposalSizeBytes.selector) { - require(_value != 0, "DeployDisputeGame: minProposalSizeBytes cannot be zero"); - _minProposalSizeBytes = _value; - } else if (_sel == this.challengePeriodSeconds.selector) { - require(_value != 0, "DeployDisputeGame: challengePeriodSeconds cannot be zero"); - _challengePeriodSeconds = _value; - } else if (_sel == this.gameType.selector) { + if (_sel == this.gameType.selector) { require(_value <= type(uint32).max, "DeployDisputeGame: gameType must fit inside uint32"); _gameType = _value; } else if (_sel == this.maxGameDepth.selector) { @@ -88,7 +71,9 @@ contract DeployDisputeGameInput is BaseDeployIO { } function set(bytes4 _sel, address _value) public { - if (_sel == this.delayedWethProxy.selector) { + if (_sel == this.vmAddress.selector) { + _vm = IBigStepper(_value); + } else if (_sel == this.delayedWethProxy.selector) { require(_value != address(0), "DeployDisputeGame: delayedWethProxy cannot be zero address"); _delayedWethProxy = IDelayedWETH(payable(_value)); } else if (_sel == this.anchorStateRegistryProxy.selector) { @@ -133,20 +118,8 @@ contract DeployDisputeGameInput is BaseDeployIO { return _standardVersionsToml; } - function mipsVersion() public view returns (uint256) { - require(_mipsVersion != 0, "DeployDisputeGame: mipsVersion not set"); - require(_mipsVersion == 1 || _mipsVersion == 2, "DeployDisputeGame: unknown mips version"); - return _mipsVersion; - } - - function minProposalSizeBytes() public view returns (uint256) { - require(_minProposalSizeBytes != 0, "DeployDisputeGame: minProposalSizeBytes not set"); - return _minProposalSizeBytes; - } - - function challengePeriodSeconds() public view returns (uint256) { - require(_challengePeriodSeconds != 0, "DeployDisputeGame: challengePeriodSeconds not set"); - return _challengePeriodSeconds; + function vmAddress() public view returns (IBigStepper) { + return _vm; } function gameKind() public view returns (string memory) { @@ -228,65 +201,30 @@ contract DeployDisputeGameOutput is BaseDeployIO { // PermissionedDisputeGame is used as the type here because it has all of the same functions as // FaultDisputeGame but with the added proposer and challenger fields. IPermissionedDisputeGame internal _disputeGameImpl; - IMIPS internal _mipsSingleton; - IPreimageOracle internal _preimageOracleSingleton; function set(bytes4 _sel, address _value) public { if (_sel == this.disputeGameImpl.selector) { require(_value != address(0), "DeployDisputeGame: disputeGameImpl cannot be zero address"); _disputeGameImpl = IPermissionedDisputeGame(_value); - } else if (_sel == this.mipsSingleton.selector) { - require(_value != address(0), "DeployDisputeGame: mipsSingleton cannot be zero address"); - _mipsSingleton = IMIPS(_value); - } else if (_sel == this.preimageOracleSingleton.selector) { - require(_value != address(0), "DeployDisputeGame: preimageOracleSingleton cannot be zero address"); - _preimageOracleSingleton = IPreimageOracle(_value); } else { revert("DeployDisputeGame: unknown selector"); } } function checkOutput(DeployDisputeGameInput _dgi) public view { - DeployUtils.assertValidContractAddress(address(_preimageOracleSingleton)); - DeployUtils.assertValidContractAddress(address(_mipsSingleton)); DeployUtils.assertValidContractAddress(address(_disputeGameImpl)); assertValidDeploy(_dgi); } - function preimageOracleSingleton() public view returns (IPreimageOracle) { - DeployUtils.assertValidContractAddress(address(_preimageOracleSingleton)); - return _preimageOracleSingleton; - } - - function mipsSingleton() public view returns (IMIPS) { - DeployUtils.assertValidContractAddress(address(_mipsSingleton)); - return _mipsSingleton; - } - function disputeGameImpl() public view returns (IPermissionedDisputeGame) { DeployUtils.assertValidContractAddress(address(_disputeGameImpl)); return _disputeGameImpl; } function assertValidDeploy(DeployDisputeGameInput _dgi) public view { - assertValidPreimageOracleSingleton(_dgi); - assertValidMipsSingleton(_dgi); assertValidDisputeGameImpl(_dgi); } - function assertValidPreimageOracleSingleton(DeployDisputeGameInput _dgi) internal view { - IPreimageOracle oracle = preimageOracleSingleton(); - - require(oracle.minProposalSize() == _dgi.minProposalSizeBytes(), "PO-10"); - require(oracle.challengePeriod() == _dgi.challengePeriodSeconds(), "PO-20"); - } - - function assertValidMipsSingleton(DeployDisputeGameInput) internal view { - IMIPS mips = mipsSingleton(); - - require(address(mips.oracle()) == address(preimageOracleSingleton()), "MIPS-10"); - } - function assertValidDisputeGameImpl(DeployDisputeGameInput _dgi) internal view { IPermissionedDisputeGame game = disputeGameImpl(); @@ -295,7 +233,7 @@ contract DeployDisputeGameOutput is BaseDeployIO { require(game.splitDepth() == _dgi.splitDepth(), "DG-30"); require(game.clockExtension().raw() == uint64(_dgi.clockExtension()), "DG-40"); require(game.maxClockDuration().raw() == uint64(_dgi.maxClockDuration()), "DG-50"); - require(game.vm() == IBigStepper(address(mipsSingleton())), "DG-60"); + require(game.vm() == _dgi.vmAddress(), "DG-60"); require(game.weth() == _dgi.delayedWethProxy(), "DG-70"); require(game.anchorStateRegistry() == _dgi.anchorStateRegistryProxy(), "DG-80"); require(game.l2ChainId() == _dgi.l2ChainId(), "DG-90"); @@ -326,68 +264,10 @@ contract DeployDisputeGame is Script { } function run(DeployDisputeGameInput _dgi, DeployDisputeGameOutput _dgo) public { - deployPreimageOracleSingleton(_dgi, _dgo); - deployMipsSingleton(_dgi, _dgo); deployDisputeGameImpl(_dgi, _dgo); _dgo.checkOutput(_dgi); } - function deployPreimageOracleSingleton(DeployDisputeGameInput _dgi, DeployDisputeGameOutput _dgo) internal { - string memory release = _dgi.release(); - string memory stdVerToml = _dgi.standardVersionsToml(); - string memory contractName = "preimage_oracle"; - IPreimageOracle singleton; - - address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); - if (existingImplementation != address(0)) { - singleton = IPreimageOracle(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { - uint256 minProposalSizeBytes = _dgi.minProposalSizeBytes(); - uint256 challengePeriodSeconds = _dgi.challengePeriodSeconds(); - vm.broadcast(msg.sender); - singleton = IPreimageOracle( - DeployUtils.create1({ - _name: "PreimageOracle", - _args: DeployUtils.encodeConstructor( - abi.encodeCall(IPreimageOracle.__constructor__, (minProposalSizeBytes, challengePeriodSeconds)) - ) - }) - ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); - } - - vm.label(address(singleton), "PreimageOracleSingleton"); - _dgo.set(_dgo.preimageOracleSingleton.selector, address(singleton)); - } - - function deployMipsSingleton(DeployDisputeGameInput _dgi, DeployDisputeGameOutput _dgo) internal { - string memory release = _dgi.release(); - string memory stdVerToml = _dgi.standardVersionsToml(); - string memory contractName = "mips"; - IMIPS singleton; - - address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); - if (existingImplementation != address(0)) { - singleton = IMIPS(payable(existingImplementation)); - } else if (isDevelopRelease(release)) { - uint256 mipsVersion = _dgi.mipsVersion(); - IPreimageOracle preimageOracle = IPreimageOracle(address(_dgo.preimageOracleSingleton())); - vm.broadcast(msg.sender); - singleton = IMIPS( - DeployUtils.create1({ - _name: mipsVersion == 1 ? "MIPS" : "MIPS64", - _args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle))) - }) - ); - } else { - revert(string.concat("DeployImplementations: failed to deploy release ", release)); - } - - vm.label(address(singleton), "MIPSSingleton"); - _dgo.set(_dgo.mipsSingleton.selector, address(singleton)); - } - function deployDisputeGameImpl(DeployDisputeGameInput _dgi, DeployDisputeGameOutput _dgo) internal { // Shove the arguments into a struct to avoid stack-too-deep errors. DisputeGameConstructorArgs memory args = DisputeGameConstructorArgs({ @@ -397,7 +277,7 @@ contract DeployDisputeGame is Script { splitDepth: _dgi.splitDepth(), clockExtension: Duration.wrap(uint64(_dgi.clockExtension())), maxClockDuration: Duration.wrap(uint64(_dgi.maxClockDuration())), - gameVm: IBigStepper(address(_dgo.mipsSingleton())), + gameVm: IBigStepper(address(_dgi.vmAddress())), delayedWethProxy: _dgi.delayedWethProxy(), anchorStateRegistryProxy: _dgi.anchorStateRegistryProxy(), l2ChainId: _dgi.l2ChainId(), From 4f8e9b519c9d10535d438cfe617f3f014df12d01 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 26 Nov 2024 08:59:41 -0700 Subject: [PATCH 41/61] ci: Tweak test timeouts (#13097) --- .circleci/config.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9d76db1d4ba..2cc977adffd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -882,6 +882,10 @@ jobs: type: string default: ethereum-optimism/latitude-1-go-e2e no_output_timeout: + description: Timeout for when CircleCI kills the job if there's no output + type: string + default: 60m + test_timeout: description: Timeout for running tests type: string default: 10m @@ -932,7 +936,7 @@ jobs: --jsonfile=./tmp/testlogs/log.json \ --rerun-fails=2 \ --packages="$formatted_packages" \ - -- -coverprofile=coverage.out -timeout=60m + -- -coverprofile=coverage.out -timeout=<> - codecov/upload: disable_search: true files: ./coverage.out @@ -1594,7 +1598,8 @@ workflows: name: op-e2e-cannon-tests notify: true mentions: "@proofs-team" - no_output_timeout: 20m + no_output_timeout: 60m + test_timeout: 59m resource_class: ethereum-optimism/latitude-fps-1 environment_overrides: | export OP_E2E_CANNON_ENABLED="true" From 9200bff0f39fb6034ca6a27a2d57da80c87ef1f4 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Tue, 26 Nov 2024 12:58:32 -0500 Subject: [PATCH 42/61] fix: restore asterisc bytecode, vendor (#13104) Restores the correct asterisc RISCV bytecode, moves the contract to the vendor folder, and changes CI so that it performs the check on the asterisc bytecode when attempting to merge into develop. --- .circleci/config.yml | 14 ++------------ .../contracts-bedrock/snapshots/semver-lock.json | 8 ++++---- .../src/{ => vendor}/asterisc/RISCV.sol | 6 ++---- 3 files changed, 8 insertions(+), 20 deletions(-) rename packages/contracts-bedrock/src/{ => vendor}/asterisc/RISCV.sol (99%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2cc977adffd..1467e9e24bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -258,7 +258,7 @@ jobs: command: | # Clone asterisc @ the pinned version to fetch remote `RISCV.sol` ASTERISC_REV="$(cat ../../versions.json | jq -r .asterisc)" - REMOTE_ASTERISC_PATH="./src/asterisc/RISCV_Remote.sol" + REMOTE_ASTERISC_PATH="./src/vendor/asterisc/RISCV_Remote.sol" git clone https://github.com/ethereum-optimism/asterisc \ -b $ASTERISC_REV && \ cp ./asterisc/rvsol/src/RISCV.sol $REMOTE_ASTERISC_PATH @@ -1324,6 +1324,7 @@ workflows: - contracts-bedrock-checks: requires: - contracts-bedrock-build + - diff-asterisc-bytecode - semgrep-scan: name: semgrep-scan-local scan_command: semgrep scan --timeout=100 --config .semgrep/rules/ --error . @@ -1693,17 +1694,6 @@ workflows: - oplabs-gcr - slack - scheduled-diff-asterisc-bytecode: - when: - or: - - equal: [build_daily, <>] - # Trigger on manual triggers if explicitly requested - - equal: [true, <>] - jobs: - - diff-asterisc-bytecode: - context: - - slack - scheduled-preimage-reproducibility: when: or: diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index c387881a61f..bfbae2fe97d 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -135,10 +135,6 @@ "initCodeHash": "0x17ea1b1c5d5a622d51c2961fde886a5498de63584e654ed1d69ee80dddbe0b17", "sourceCodeHash": "0x0fa0633a769e73f5937514c0003ba7947a1c275bbe5b85d78879c42f0ed8895b" }, - "src/asterisc/RISCV.sol": { - "initCodeHash": "0x8d47aa0b81d7fe6bd0aeac18f26d7c0b285f58740bb9d92dac0ddf706c85309f", - "sourceCodeHash": "0xaebcda0a16da65fc7833672073ea6872c40d1ba722f0a6515c4a293e380f96c6" - }, "src/cannon/MIPS.sol": { "initCodeHash": "0xb4aec227019dacd6194d6aeb9ca68c23c60b95618d18a4ebc09243514aeb1f05", "sourceCodeHash": "0x4d43b3f2918486aa76d2d59ac42e4f6aa2f58538c7e95a5cb99b63c9588b5f1c" @@ -215,6 +211,10 @@ "initCodeHash": "0x049f3c86965e575a370b14f7f49f3f15436ffb5ee1059615bb708659d7aae7de", "sourceCodeHash": "0x5dc6b0b4ae4ab29085c52f74a4498d8a3d04928b844491749cd7186623e8b967" }, + "src/vendor/asterisc/RISCV.sol": { + "initCodeHash": "0x6b4323061187f2c8efe8de43bf1ecdc0798e2d95ad69470ed4151dadc094fedf", + "sourceCodeHash": "0x26cae049cf171efcc84c946a400704c30ebec5dba4f1548d1f1529f68f56c1ec" + }, "src/vendor/eas/EAS.sol": { "initCodeHash": "0xf96d1ebc530ed95e2dffebcfa2b4a1f18103235e6352d97838b77b7a2c14567b", "sourceCodeHash": "0xbeca762929db37f1c7a2067e136c616f563ca18e85871ad7ae2d3ff55a16e6cb" diff --git a/packages/contracts-bedrock/src/asterisc/RISCV.sol b/packages/contracts-bedrock/src/vendor/asterisc/RISCV.sol similarity index 99% rename from packages/contracts-bedrock/src/asterisc/RISCV.sol rename to packages/contracts-bedrock/src/vendor/asterisc/RISCV.sol index 50afd85fe6c..09fa93a0fcd 100644 --- a/packages/contracts-bedrock/src/asterisc/RISCV.sol +++ b/packages/contracts-bedrock/src/vendor/asterisc/RISCV.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Interfaces import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; @@ -9,15 +8,14 @@ import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; /// @notice The RISCV contract emulates a single RISCV hart cycle statelessly, using memory proofs to verify the /// instruction and optional memory access' inclusion in the memory merkle root provided in the trusted /// prestate witness. -/// This contract has been vendorized from the Asterisc project. The original source code can be found at /// @dev https://github.com/ethereum-optimism/asterisc contract RISCV is IBigStepper { /// @notice The preimage oracle contract. IPreimageOracle public oracle; /// @notice The version of the contract. - /// @custom:semver 1.1.0-rc.3 - string public constant version = "1.1.0-rc.3"; + /// @custom:semver 1.1.0-rc.2 + string public constant version = "1.1.0-rc.2"; /// @param _oracle The preimage oracle contract. constructor(IPreimageOracle _oracle) { From 51a036d2eca82ad947f4446733cffe12b55e96f4 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 26 Nov 2024 11:27:21 -0700 Subject: [PATCH 43/61] op-node: Fix panic after closing P2P (#13106) When the op-node is closed, it also closes the P2P node. To prevent future usage, `n.p2pNode` is set to `nil`. However, the AsyncGossiper can still sometimes send gossip messages to the `OpNode` struct after close. Since `n.p2pNode` is `nil` at this point, the node would panic. This PR updates the `OpNode` implementation to check for this case. Access is protected via a mutex to prevent concurrency problems. --- op-node/node/node.go | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/op-node/node/node.go b/op-node/node/node.go index 2727552b819..8bf8040b465 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + gosync "sync" "sync/atomic" "time" @@ -60,6 +61,7 @@ type OpNode struct { l2Source *sources.EngineClient // L2 Execution Engine RPC bindings server *rpcServer // RPC server hosting the rollup-node API p2pNode *p2p.NodeP2P // P2P node functionality + p2pMu gosync.Mutex // protects p2pNode p2pSigner p2p.Signer // p2p gossip application messages will be signed with this signer tracer Tracer // tracer to get events for testing/debugging runCfg *RuntimeConfig // runtime configurables @@ -434,8 +436,9 @@ func (n *OpNode) initRPCServer(cfg *Config) error { if err != nil { return err } - if n.p2pEnabled() { - server.EnableP2P(p2p.NewP2PAPIBackend(n.p2pNode, n.log, n.metrics)) + + if p2pNode := n.getP2PNodeIfEnabled(); p2pNode != nil { + server.EnableP2P(p2p.NewP2PAPIBackend(p2pNode, n.log, n.metrics)) } if cfg.RPC.EnableAdmin { server.EnableAdminAPI(NewAdminAPI(n.l2Driver, n.metrics, n.log)) @@ -487,6 +490,8 @@ func (n *OpNode) p2pEnabled() bool { } func (n *OpNode) initP2P(cfg *Config) (err error) { + n.p2pMu.Lock() + defer n.p2pMu.Unlock() if n.p2pNode != nil { panic("p2p node already initialized") } @@ -580,13 +585,13 @@ func (n *OpNode) PublishL2Payload(ctx context.Context, envelope *eth.ExecutionPa n.tracer.OnPublishL2Payload(ctx, envelope) // publish to p2p, if we are running p2p at all - if n.p2pEnabled() { + if p2pNode := n.getP2PNodeIfEnabled(); p2pNode != nil { payload := envelope.ExecutionPayload if n.p2pSigner == nil { return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) } n.log.Info("Publishing signed execution payload on p2p", "id", payload.ID()) - return n.p2pNode.GossipOut().PublishL2Payload(ctx, envelope, n.p2pSigner) + return p2pNode.GossipOut().PublishL2Payload(ctx, envelope, n.p2pSigner) } // if p2p is not enabled then we just don't publish the payload return nil @@ -594,7 +599,7 @@ func (n *OpNode) PublishL2Payload(ctx context.Context, envelope *eth.ExecutionPa func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, envelope *eth.ExecutionPayloadEnvelope) error { // ignore if it's from ourselves - if n.p2pEnabled() && from == n.p2pNode.Host().ID() { + if p2pNode := n.getP2PNodeIfEnabled(); p2pNode != nil && from == p2pNode.Host().ID() { return nil } @@ -615,7 +620,7 @@ func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, envelope * } func (n *OpNode) RequestL2Range(ctx context.Context, start, end eth.L2BlockRef) error { - if n.p2pEnabled() && n.p2pNode.AltSyncEnabled() { + if p2pNode := n.getP2PNodeIfEnabled(); p2pNode != nil && p2pNode.AltSyncEnabled() { if unixTimeStale(start.Time, 12*time.Hour) { n.log.Debug( "ignoring request to sync L2 range, timestamp is too old for p2p", @@ -624,7 +629,7 @@ func (n *OpNode) RequestL2Range(ctx context.Context, start, end eth.L2BlockRef) "start_time", start.Time) return nil } - return n.p2pNode.RequestL2Range(ctx, start, end) + return p2pNode.RequestL2Range(ctx, start, end) } n.log.Debug("ignoring request to sync L2 range, no sync method available", "start", start, "end", end) return nil @@ -636,7 +641,7 @@ func unixTimeStale(timestamp uint64, duration time.Duration) bool { } func (n *OpNode) P2P() p2p.Node { - return n.p2pNode + return n.getP2PNodeIfEnabled() } func (n *OpNode) RuntimeConfig() ReadonlyRuntimeConfig { @@ -671,6 +676,8 @@ func (n *OpNode) Stop(ctx context.Context) error { result = multierror.Append(result, fmt.Errorf("error stopping sequencer: %w", err)) } } + + n.p2pMu.Lock() if n.p2pNode != nil { if err := n.p2pNode.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close p2p node: %w", err)) @@ -678,6 +685,8 @@ func (n *OpNode) Stop(ctx context.Context) error { // Prevent further use of p2p. n.p2pNode = nil } + n.p2pMu.Unlock() + if n.p2pSigner != nil { if err := n.p2pSigner.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close p2p signer: %w", err)) @@ -778,3 +787,13 @@ func (n *OpNode) HTTPEndpoint() string { } return fmt.Sprintf("http://%s", n.server.Addr().String()) } + +func (n *OpNode) getP2PNodeIfEnabled() *p2p.NodeP2P { + if !n.p2pEnabled() { + return nil + } + + n.p2pMu.Lock() + defer n.p2pMu.Unlock() + return n.p2pNode +} From c73f45b6e2d84bef960e71a092496f50d76046d3 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Tue, 26 Nov 2024 13:51:15 -0500 Subject: [PATCH 44/61] maint: minor cleanup of foundry configuration (#13102) Very small cleanup of the foundry config file. --- packages/contracts-bedrock/foundry.toml | 53 +++++++++++++------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 6bd441ca3cd..5812b129f91 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -1,15 +1,22 @@ ################################################################ -# PROFILE: DEFAULT (Local) # +# PROFILE: DEFAULT (local) # ################################################################ [profile.default] -# Compilation settings src = 'src' out = 'forge-artifacts' script = 'scripts' +build_info_path = 'artifacts/build-info' + optimizer = true optimizer_runs = 999999 + +extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] +bytecode_hash = 'none' +ast = true +evm_version = "cancun" + remappings = [ '@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts', '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts', @@ -24,22 +31,7 @@ remappings = [ 'kontrol-cheatcodes/=lib/kontrol-cheatcodes/src', 'gelato/=lib/automate/contracts' ] -extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] -bytecode_hash = 'none' -build_info_path = 'artifacts/build-info' -ast = true -evm_version = "cancun" -# 5159 error code is selfdestruct error code -ignored_error_codes = ["transient-storage", "code-size", "init-code-size", 5159] -# We set the gas limit to max int64 to avoid running out of gas during testing, since the default -# gas limit is 1B and some of our tests require more gas than that, such as `test_callWithMinGas_noLeakageLow_succeeds`. -# We use this gas limit since it was the default gas limit prior to https://github.com/foundry-rs/foundry/pull/8274. -# Due to toml-rs limitations, if you increase the gas limit above this value it must be a string. -gas_limit = 9223372036854775807 - -# Test / Script Runner Settings -ffi = true fs_permissions = [ { access='read-write', path='./.resource-metering.csv' }, { access='read-write', path='./snapshots/' }, @@ -52,7 +44,17 @@ fs_permissions = [ { access='read', path='./kout-deployment' }, { access='read', path='./test/fixtures' }, ] -libs = ["node_modules", "lib"] + +# 5159 error code is selfdestruct error code +ignored_error_codes = ["transient-storage", "code-size", "init-code-size", 5159] +ffi = true + +# We set the gas limit to max int64 to avoid running out of gas during testing, since the default +# gas limit is 1B and some of our tests require more gas than that, such as +# test_callWithMinGas_noLeakageLow_succeeds. We use this gas limit since it was the default gas +# limit prior to https://github.com/foundry-rs/foundry/pull/8274. Due to toml-rs limitations, if +# you increase the gas limit above this value it must be a string. +gas_limit = 9223372036854775807 [fuzz] runs = 64 @@ -67,17 +69,19 @@ wrap_comments=true # PROFILE: CI # ################################################################ -[profile.ci] -fuzz = { runs = 512 } +[profile.ci.fuzz] +runs = 512 [profile.ci.invariant] runs = 256 depth = 32 -[profile.ciheavy] -# fuzz = { runs = 20000 } -# temporary reduce fuzz runs to unblock CI -fuzz = { runs = 200 } +################################################################ +# PROFILE: CIHEAVY # +################################################################ + +[profile.ciheavy.fuzz] +runs = 20000 [profile.ciheavy.invariant] runs = 128 @@ -93,7 +97,6 @@ optimizer = false ################################################################ # PROFILE: KONTROL # ################################################################ -# See test/kontrol/README.md for an explanation of how the profiles are configured [profile.kprove] src = 'test/kontrol/proofs' From e8744d5355b400e5b6282989dff3f470f4f9200c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:33:43 -0700 Subject: [PATCH 45/61] dependabot(gomod): bump github.com/minio/minio-go/v7 (#13109) Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.80 to 7.0.81. - [Release notes](https://github.com/minio/minio-go/releases) - [Commits](https://github.com/minio/minio-go/compare/v7.0.80...v7.0.81) --- updated-dependencies: - dependency-name: github.com/minio/minio-go/v7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7ef9af899b0..593ee186ad1 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.12.0 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/mattn/go-isatty v0.0.20 - github.com/minio/minio-go/v7 v7.0.80 + github.com/minio/minio-go/v7 v7.0.81 github.com/multiformats/go-base32 v0.1.0 github.com/multiformats/go-multiaddr v0.14.0 github.com/multiformats/go-multiaddr-dns v0.4.0 diff --git a/go.sum b/go.sum index 2d20e1e8272..9b62f53e6c8 100644 --- a/go.sum +++ b/go.sum @@ -524,8 +524,8 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4S github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.80 h1:2mdUHXEykRdY/BigLt3Iuu1otL0JTogT0Nmltg0wujk= -github.com/minio/minio-go/v7 v7.0.80/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0= +github.com/minio/minio-go/v7 v7.0.81 h1:SzhMN0TQ6T/xSBu6Nvw3M5M8voM+Ht8RH3hE8S7zxaA= +github.com/minio/minio-go/v7 v7.0.81/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= From 980b261fdd81c9caef657a3929f2c4ae0ec3a897 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:49:21 +0000 Subject: [PATCH 46/61] dependabot(gomod): bump github.com/multiformats/go-multiaddr-dns (#13110) Bumps [github.com/multiformats/go-multiaddr-dns](https://github.com/multiformats/go-multiaddr-dns) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/multiformats/go-multiaddr-dns/releases) - [Commits](https://github.com/multiformats/go-multiaddr-dns/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: github.com/multiformats/go-multiaddr-dns dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 593ee186ad1..3e36ecc8325 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/minio/minio-go/v7 v7.0.81 github.com/multiformats/go-base32 v0.1.0 github.com/multiformats/go-multiaddr v0.14.0 - github.com/multiformats/go-multiaddr-dns v0.4.0 + github.com/multiformats/go-multiaddr-dns v0.4.1 github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 9b62f53e6c8..4302fb00204 100644 --- a/go.sum +++ b/go.sum @@ -551,8 +551,8 @@ github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= -github.com/multiformats/go-multiaddr-dns v0.4.0 h1:P76EJ3qzBXpUXZ3twdCDx/kvagMsNo0LMFXpyms/zgU= -github.com/multiformats/go-multiaddr-dns v0.4.0/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= +github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= +github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= From 98a1d928686f83250184f3946eb5b066a6c5d61b Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 27 Nov 2024 06:53:47 +1000 Subject: [PATCH 47/61] op-challenger: Allow specifying a chain ID as network. (#13027) op-program supports custom configs identified by chain ID so make sure op-challenger can pass through a chain ID option even if it isn't a known network. --- op-challenger/cmd/main_test.go | 7 +++++++ op-challenger/config/config.go | 6 +++++- op-challenger/config/config_test.go | 12 ++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/op-challenger/cmd/main_test.go b/op-challenger/cmd/main_test.go index 1de92468306..daa4e44f26b 100644 --- a/op-challenger/cmd/main_test.go +++ b/op-challenger/cmd/main_test.go @@ -177,6 +177,13 @@ func TestNetwork(t *testing.T) { t.Run("UnknownNetwork", func(t *testing.T) { verifyArgsInvalid(t, "unknown chain: not-a-network", addRequiredArgsExcept(types.TraceTypeAlphabet, "--game-factory-address", "--network=not-a-network")) }) + + t.Run("ChainIDAllowedWhenGameFactoryAddressSupplied", func(t *testing.T) { + addr := common.Address{0xbb, 0xcc, 0xdd} + cfg := configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--game-factory-address", "--network=1234", "--game-factory-address="+addr.Hex())) + require.Equal(t, addr, cfg.GameFactoryAddress) + require.Equal(t, "1234", cfg.Cannon.Network) + }) } func TestGameAllowlist(t *testing.T) { diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index 9f4a5f5f375..6faf7c9fdca 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -6,6 +6,7 @@ import ( "net/url" "runtime" "slices" + "strconv" "time" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" @@ -230,7 +231,10 @@ func (c Config) Check() error { return ErrCannonNetworkAndL2Genesis } if ch := chaincfg.ChainByName(c.Cannon.Network); ch == nil { - return fmt.Errorf("%w: %v", ErrCannonNetworkUnknown, c.Cannon.Network) + // Check if this looks like a chain ID that could be a custom chain configuration. + if _, err := strconv.ParseUint(c.Cannon.Network, 10, 32); err != nil { + return fmt.Errorf("%w: %v", ErrCannonNetworkUnknown, c.Cannon.Network) + } } } if c.CannonAbsolutePreState == "" && c.CannonAbsolutePreStateBaseURL == nil { diff --git a/op-challenger/config/config_test.go b/op-challenger/config/config_test.go index 0d922b77fe9..bf910ab83e8 100644 --- a/op-challenger/config/config_test.go +++ b/op-challenger/config/config_test.go @@ -232,6 +232,18 @@ func TestCannonRequiredArgs(t *testing.T) { require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown) }) + t.Run(fmt.Sprintf("TestNetworkMayBeAnyChainID-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.Cannon.Network = "467294" + require.NoError(t, cfg.Check()) + }) + + t.Run(fmt.Sprintf("TestNetworkInvalidWhenNotEntirelyNumeric-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.Cannon.Network = "467294a" + require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown) + }) + t.Run(fmt.Sprintf("TestDebugInfoEnabled-%v", traceType), func(t *testing.T) { cfg := validConfig(traceType) require.True(t, cfg.Cannon.DebugInfo) From 72eb3116c2f6ff573099a8cafc8f35415138850c Mon Sep 17 00:00:00 2001 From: tre Date: Tue, 26 Nov 2024 14:11:00 -0800 Subject: [PATCH 48/61] feat(protoype): enable superchainWETH native transfers (#12710) --- .../snapshots/abi/SuperchainWETH.json | 119 ++++++++++ .../snapshots/semver-lock.json | 4 +- .../src/L2/SuperchainWETH.sol | 80 ++++++- .../src/L2/interfaces/ISuperchainWETH.sol | 8 + .../test/L2/SuperchainWETH.t.sol | 209 +++++++++++++++++- 5 files changed, 412 insertions(+), 8 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json index a8b4365d742..e8df09a8064 100644 --- a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json @@ -143,6 +143,53 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "relayETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + } + ], + "name": "sendETH", + "outputs": [ + { + "internalType": "bytes32", + "name": "msgHash_", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -361,6 +408,68 @@ "name": "Deposit", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "source", + "type": "uint256" + } + ], + "name": "RelayETH", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "destination", + "type": "uint256" + } + ], + "name": "SendETH", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -405,6 +514,11 @@ "name": "Withdrawal", "type": "event" }, + { + "inputs": [], + "name": "InvalidCrossDomainSender", + "type": "error" + }, { "inputs": [], "name": "NotCustomGasToken", @@ -414,5 +528,10 @@ "inputs": [], "name": "Unauthorized", "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index bfbae2fe97d..35696bc7bf1 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -128,8 +128,8 @@ "sourceCodeHash": "0x617aa994f659c5d8ebd54128d994f86f5b175ceca095b024b8524a7898e8ae62" }, "src/L2/SuperchainWETH.sol": { - "initCodeHash": "0x90aad5698e09994909331dd9665d99a8d5a53e45ba792bf47e4c2efbd48f7699", - "sourceCodeHash": "0x35f0ffcfa027f736b496f3fd2640c043648a49ce325083486ce27f63bfec6d08" + "initCodeHash": "0xac4cab1ee7f0a5de8362ddc37e1de92e816aee3fdd4e31c0ba0fd9b03568f0f0", + "sourceCodeHash": "0x1fc6439f7a5fac2e264d5e057593844d252cdaa12c2b1eaa2fb08cbb911a9f35" }, "src/L2/WETH.sol": { "initCodeHash": "0x17ea1b1c5d5a622d51c2961fde886a5498de63584e654ed1d69ee80dddbe0b17", diff --git a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol index d5c37d9cc76..912f1aa3d86 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol @@ -5,16 +5,18 @@ pragma solidity 0.8.15; import { WETH98 } from "src/universal/WETH98.sol"; // Libraries +import { NotCustomGasToken, Unauthorized, ZeroAddress } from "src/libraries/errors/CommonErrors.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Preinstalls } from "src/libraries/Preinstalls.sol"; +import { SafeSend } from "src/universal/SafeSend.sol"; // Interfaces import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; import { IERC7802, IERC165 } from "src/L2/interfaces/IERC7802.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000024 @@ -23,9 +25,26 @@ import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErro /// within the superchain. SuperchainWETH can be converted into native ETH on chains that /// do not use a custom gas token. contract SuperchainWETH is WETH98, IERC7802, ISemver { + /// @notice Thrown when attempting to relay a message and the cross domain message sender is not SuperchainWETH. + error InvalidCrossDomainSender(); + + /// @notice Emitted when ETH is sent from one chain to another. + /// @param from Address of the sender. + /// @param to Address of the recipient. + /// @param amount Amount of ETH sent. + /// @param destination Chain ID of the destination chain. + event SendETH(address indexed from, address indexed to, uint256 amount, uint256 destination); + + /// @notice Emitted whenever ETH is successfully relayed on this chain. + /// @param from Address of the msg.sender of sendETH on the source chain. + /// @param to Address of the recipient. + /// @param amount Amount of ETH relayed. + /// @param source Chain ID of the source chain. + event RelayETH(address indexed from, address indexed to, uint256 amount, uint256 source); + /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.11 - string public constant version = "1.0.0-beta.11"; + /// @custom:semver 1.0.0-beta.12 + string public constant version = "1.0.0-beta.12"; /// @inheritdoc WETH98 function deposit() public payable override { @@ -69,8 +88,9 @@ contract SuperchainWETH is WETH98, IERC7802, ISemver { _mint(_to, _amount); - // Mint from ETHLiquidity contract. + // Withdraw from ETHLiquidity contract. if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + // NOTE: 'mint' will soon change to 'withdraw'. IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(_amount); } @@ -85,8 +105,9 @@ contract SuperchainWETH is WETH98, IERC7802, ISemver { _burn(_from, _amount); - // Burn to ETHLiquidity contract. + // Deposit to ETHLiquidity contract. if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + // NOTE: 'burn' will soon change to 'deposit'. IETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: _amount }(); } @@ -98,4 +119,53 @@ contract SuperchainWETH is WETH98, IERC7802, ISemver { return _interfaceId == type(IERC7802).interfaceId || _interfaceId == type(IERC20).interfaceId || _interfaceId == type(IERC165).interfaceId; } + + /// @notice Sends ETH to some target address on another chain. + /// @param _to Address to send ETH to. + /// @param _chainId Chain ID of the destination chain. + /// @return msgHash_ Hash of the message sent. + function sendETH(address _to, uint256 _chainId) external payable returns (bytes32 msgHash_) { + if (_to == address(0)) revert ZeroAddress(); + + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + revert NotCustomGasToken(); + } + + // NOTE: 'burn' will soon change to 'deposit'. + IETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: msg.value }(); + + msgHash_ = IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).sendMessage({ + _destination: _chainId, + _target: address(this), + _message: abi.encodeCall(this.relayETH, (msg.sender, _to, msg.value)) + }); + + emit SendETH(msg.sender, _to, msg.value, _chainId); + } + + /// @notice Relays ETH received from another chain. + /// @param _from Address of the msg.sender of sendETH on the source chain. + /// @param _to Address to relay ETH to. + /// @param _amount Amount of ETH to relay. + function relayETH(address _from, address _to, uint256 _amount) external { + if (msg.sender != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER) revert Unauthorized(); + + (address crossDomainMessageSender, uint256 source) = + IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).crossDomainMessageContext(); + + if (crossDomainMessageSender != address(this)) revert InvalidCrossDomainSender(); + + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + // Since ETH is not the native asset on custom gas token chains, send SuperchainWETH to the recipient. + _mint(_to, _amount); + } else { + // NOTE: 'mint' will soon change to 'withdraw'. + IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(_amount); + + // This is a forced ETH send to the recipient, the recipient should NOT expect to be called. + new SafeSend{ value: _amount }(payable(_to)); + } + + emit RelayETH(_from, _to, _amount, source); + } } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol index fa10b237dbb..4a4bbe35372 100644 --- a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol @@ -8,10 +8,18 @@ import { ISemver } from "src/universal/interfaces/ISemver.sol"; interface ISuperchainWETH is IWETH98, IERC7802, ISemver { error Unauthorized(); error NotCustomGasToken(); + error InvalidCrossDomainSender(); + error ZeroAddress(); + + event SendETH(address indexed from, address indexed to, uint256 amount, uint256 destination); + + event RelayETH(address indexed from, address indexed to, uint256 amount, uint256 source); function balanceOf(address src) external view returns (uint256); function withdraw(uint256 _amount) external; function supportsInterface(bytes4 _interfaceId) external view returns (bool); + function sendETH(address _to, uint256 _chainId) external payable returns (bytes32 msgHash_); + function relayETH(address _from, address _to, uint256 _amount) external; function __constructor__() external; } diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol index 88ff2ada895..c47bec6252d 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -6,7 +6,7 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; +import { NotCustomGasToken, Unauthorized, ZeroAddress } from "src/libraries/errors/CommonErrors.sol"; import { Preinstalls } from "src/libraries/Preinstalls.sol"; // Interfaces @@ -14,6 +14,7 @@ import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; import { IERC7802, IERC165 } from "src/L2/interfaces/IERC7802.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; /// @title SuperchainWETH_Test /// @notice Contract for testing the SuperchainWETH contract. @@ -33,6 +34,10 @@ contract SuperchainWETH_Test is CommonTest { /// @notice Emitted when a crosschain transfer burns tokens. event CrosschainBurn(address indexed from, uint256 amount, address indexed sender); + event SendETH(address indexed from, address indexed to, uint256 amount, uint256 destination); + + event RelayETH(address indexed from, address indexed to, uint256 amount, uint256 source); + address internal constant ZERO_ADDRESS = address(0); /// @notice Test setup. @@ -475,4 +480,206 @@ contract SuperchainWETH_Test is CommonTest { vm.assume(_interfaceId != type(IERC20).interfaceId); assertFalse(superchainWeth.supportsInterface(_interfaceId)); } + + /// @notice Tests the `sendETH` function reverts when the address `_to` is zero. + function testFuzz_sendETH_zeroAddressTo_reverts(address _sender, uint256 _amount, uint256 _chainId) public { + // Expect the revert with `ZeroAddress` selector + vm.expectRevert(ZeroAddress.selector); + + vm.deal(_sender, _amount); + vm.prank(_sender); + // Call the `sendETH` function with the zero address as `_to` + superchainWeth.sendETH{ value: _amount }(ZERO_ADDRESS, _chainId); + } + + /// @notice Tests the `sendETH` function burns the sender ETH, sends the message, and emits the `SendETH` + /// event. + function testFuzz_sendETH_fromNonCustomGasTokenChain_succeeds( + address _sender, + address _to, + uint256 _amount, + uint256 _chainId, + bytes32 _msgHash + ) + external + { + // Assume + vm.assume(_sender != ZERO_ADDRESS); + vm.assume(_to != ZERO_ADDRESS); + _amount = bound(_amount, 0, type(uint248).max - 1); + + // Arrange + vm.deal(_sender, _amount); + _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(false)); + + // Get the total balance of `_sender` before the send to compare later on the assertions + uint256 _senderBalanceBefore = _sender.balance; + + // Look for the emit of the `SendETH` event + vm.expectEmit(address(superchainWeth)); + emit SendETH(_sender, _to, _amount, _chainId); + + // Expect the call to the `burn` function in the `ETHLiquidity` contract + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.burn, ()), 1); + + // Mock the call over the `sendMessage` function and expect it to be called properly + bytes memory _message = abi.encodeCall(superchainWeth.relayETH, (_sender, _to, _amount)); + _mockAndExpect( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.sendMessage, (_chainId, address(superchainWeth), _message)), + abi.encode(_msgHash) + ); + + // Call the `sendETH` function + vm.prank(_sender); + bytes32 _returnedMsgHash = superchainWeth.sendETH{ value: _amount }(_to, _chainId); + + // Check the message hash was generated correctly + assertEq(_msgHash, _returnedMsgHash); + + // Check the total supply and balance of `_sender` after the send were updated correctly + assertEq(_sender.balance, _senderBalanceBefore - _amount); + } + + /// @notice Tests the `sendETH` function reverts when called on a custom gas token chain. + function testFuzz_sendETH_fromCustomGasTokenChain_fails( + address _sender, + address _to, + uint256 _amount, + uint256 _chainId + ) + external + { + // Assume + vm.assume(_sender != ZERO_ADDRESS); + vm.assume(_to != ZERO_ADDRESS); + _amount = bound(_amount, 0, type(uint248).max - 1); + + // Arrange + vm.deal(_sender, _amount); + _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Call the `sendETH` function + vm.prank(_sender); + vm.expectRevert(NotCustomGasToken.selector); + superchainWeth.sendETH{ value: _amount }(_to, _chainId); + } + + /// @notice Tests the `relayETH` function reverts when the caller is not the L2ToL2CrossDomainMessenger. + function testFuzz_relayETH_notMessenger_reverts(address _caller, address _to, uint256 _amount) public { + // Ensure the caller is not the messenger + vm.assume(_caller != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + // Expect the revert with `Unauthorized` selector + vm.expectRevert(Unauthorized.selector); + + // Call the `relayETH` function with the non-messenger caller + vm.prank(_caller); + superchainWeth.relayETH(_caller, _to, _amount); + } + + /// @notice Tests the `relayETH` function reverts when the `crossDomainMessageSender` that sent the message is not + /// the same SuperchainWETH. + function testFuzz_relayETH_notCrossDomainSender_reverts( + address _crossDomainMessageSender, + uint256 _source, + address _to, + uint256 _amount + ) + public + { + vm.assume(_crossDomainMessageSender != address(superchainWeth)); + + // Mock the call over the `crossDomainMessageContext` function setting a wrong sender + vm.mockCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageContext, ()), + abi.encode(_crossDomainMessageSender, _source) + ); + + // Expect the revert with `InvalidCrossDomainSender` selector + vm.expectRevert(ISuperchainWETH.InvalidCrossDomainSender.selector); + + // Call the `relayETH` function with the sender caller + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.relayETH(_crossDomainMessageSender, _to, _amount); + } + + /// @notice Tests the `relayETH` function succeeds and sends SuperchainWETH to the recipient on a custom gas token + /// chain. + function testFuzz_relayETH_fromCustomGasTokenChain_succeeds( + address _from, + address _to, + uint256 _amount, + uint256 _source + ) + public + { + // Assume + vm.assume(_to != ZERO_ADDRESS); + _amount = bound(_amount, 0, type(uint248).max - 1); + + // Get the balance of `_to` before the mint to compare later on the assertions + uint256 _toBalanceBefore = superchainWeth.balanceOf(_to); + + // Look for the emit of the `Transfer` event + vm.expectEmit(address(superchainWeth)); + emit Transfer(ZERO_ADDRESS, _to, _amount); + + // Look for the emit of the `RelayETH` event + vm.expectEmit(address(superchainWeth)); + emit RelayETH(_from, _to, _amount, _source); + + // Arrange + _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + _mockAndExpect( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageContext, ()), + abi.encode(address(superchainWeth), _source) + ); + // Expect to not call the `mint` function in the `ETHLiquidity` contract + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.mint, (_amount)), 0); + + // Act + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.relayETH(_from, _to, _amount); + + // Check the total supply and balance of `_to` after the mint were updated correctly + assertEq(superchainWeth.balanceOf(_to), _toBalanceBefore + _amount); + assertEq(superchainWeth.totalSupply(), 0); + assertEq(address(superchainWeth).balance, 0); + } + + /// @notice Tests the `relayETH` function relays the proper amount of ETH and emits the `RelayETH` event. + function testFuzz_relayETH_succeeds(address _from, address _to, uint256 _amount, uint256 _source) public { + // Assume + vm.assume(_to != ZERO_ADDRESS); + assumePayable(_to); + _amount = bound(_amount, 0, type(uint248).max - 1); + + // Arrange + vm.deal(address(superchainWeth), _amount); + vm.deal(Predeploys.ETH_LIQUIDITY, _amount); + _mockAndExpect(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(false)); + _mockAndExpect( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageContext, ()), + abi.encode(address(superchainWeth), _source) + ); + + uint256 _toBalanceBefore = _to.balance; + + // Look for the emit of the `RelayETH` event + vm.expectEmit(address(superchainWeth)); + emit RelayETH(_from, _to, _amount, _source); + + // Expect the call to the `mint` function in the `ETHLiquidity` contract + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.mint, (_amount)), 1); + + // Call the `RelayETH` function with the messenger caller + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.relayETH(_from, _to, _amount); + + assertEq(_to.balance, _toBalanceBefore + _amount); + } } From 91099581e7e129921d794b0a8580ef2c5bb445d8 Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Wed, 27 Nov 2024 10:44:07 -0500 Subject: [PATCH 49/61] fix: SuperchainWETH test flake (#13115) Fixes a flake that existed inside of the SuperchainWETH test suite. Was caught by the heavy fuzz test. --- .../test/L2/SuperchainWETH.t.sol | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol index c47bec6252d..621acaa3aef 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -329,8 +329,8 @@ contract SuperchainWETH_Test is CommonTest { /// @notice Test that the internal mint function reverts to protect against accidentally changing the visibility. function testFuzz_calling_internalMintFunction_reverts(address _caller, address _to, uint256 _amount) public { // Arrange - bytes memory _calldata = abi.encodeWithSignature("_mint(address,uint256)", _to, _amount); // nosemgrep: - // sol-style-use-abi-encodecall + // nosemgrep: sol-style-use-abi-encodecall + bytes memory _calldata = abi.encodeWithSignature("_mint(address,uint256)", _to, _amount); vm.expectRevert(bytes("")); // Act @@ -344,8 +344,8 @@ contract SuperchainWETH_Test is CommonTest { /// @notice Test that the mint function reverts to protect against accidentally changing the visibility. function testFuzz_calling_mintFunction_reverts(address _caller, address _to, uint256 _amount) public { // Arrange - bytes memory _calldata = abi.encodeWithSignature("mint(address,uint256)", _to, _amount); // nosemgrep: - // sol-style-use-abi-encodecall + // nosemgrep: sol-style-use-abi-encodecall + bytes memory _calldata = abi.encodeWithSignature("mint(address,uint256)", _to, _amount); vm.expectRevert(bytes("")); // Act @@ -359,8 +359,8 @@ contract SuperchainWETH_Test is CommonTest { /// @notice Test that the internal burn function reverts to protect against accidentally changing the visibility. function testFuzz_calling_internalBurnFunction_reverts(address _caller, address _from, uint256 _amount) public { // Arrange - bytes memory _calldata = abi.encodeWithSignature("_burn(address,uint256)", _from, _amount); // nosemgrep: - // sol-style-use-abi-encodecall + // nosemgrep: sol-style-use-abi-encodecall + bytes memory _calldata = abi.encodeWithSignature("_burn(address,uint256)", _from, _amount); vm.expectRevert(bytes("")); // Act @@ -374,8 +374,8 @@ contract SuperchainWETH_Test is CommonTest { /// @notice Test that the burn function reverts to protect against accidentally changing the visibility. function testFuzz_calling_burnFuunction_reverts(address _caller, address _from, uint256 _amount) public { // Arrange - bytes memory _calldata = abi.encodeWithSignature("burn(address,uint256)", _from, _amount); // nosemgrep: - // sol-style-use-abi-encodecall + // nosemgrep: sol-style-use-abi-encodecall + bytes memory _calldata = abi.encodeWithSignature("burn(address,uint256)", _from, _amount); vm.expectRevert(bytes("")); // Act @@ -504,6 +504,7 @@ contract SuperchainWETH_Test is CommonTest { external { // Assume + vm.assume(_sender != address(ethLiquidity)); vm.assume(_sender != ZERO_ADDRESS); vm.assume(_to != ZERO_ADDRESS); _amount = bound(_amount, 0, type(uint248).max - 1); From c8f4b3a0e05c0710345626b71c0f1937ccd845f0 Mon Sep 17 00:00:00 2001 From: Sam Stokes <35908605+bitwiseguy@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:43:37 -0500 Subject: [PATCH 50/61] op-deployer: add intent-config-type (#12970) * op-deployer: add config-intent-type * op-deployer: revert name change of GasLimit * op-deployer: add Intent.setStandardValues and Intent.validateStandardValues * op-deployer: improve standard intent-config err messages * op-deployr: chain intent custom err types * op-deployer: add unit test for inent.validateStandardValues * linter fix * add intent-config-type custom * add intent-config-type strict * add intent-config-type standard-overrides,strict-overrides * refactor intent.ConfigType validation methods, add intent NewIntent* funcs * add TestValidateCustomValues, refactor contract tag check * remove duplicate chainIntent.Check() code * fix SuperchainRoles.ProxyAdminOwner for standard chains --- op-deployer/pkg/deployer/apply.go | 3 + op-deployer/pkg/deployer/artifacts/locator.go | 6 +- op-deployer/pkg/deployer/flags.go | 15 +- op-deployer/pkg/deployer/init.go | 57 +-- .../deployer/integration_test/apply_test.go | 6 +- op-deployer/pkg/deployer/pipeline/init.go | 4 +- op-deployer/pkg/deployer/standard/standard.go | 38 +- .../pkg/deployer/state/chain_intent.go | 82 +++++ op-deployer/pkg/deployer/state/intent.go | 337 +++++++++++++----- op-deployer/pkg/deployer/state/intent_test.go | 89 +++++ 10 files changed, 478 insertions(+), 159 deletions(-) create mode 100644 op-deployer/pkg/deployer/state/chain_intent.go create mode 100644 op-deployer/pkg/deployer/state/intent_test.go diff --git a/op-deployer/pkg/deployer/apply.go b/op-deployer/pkg/deployer/apply.go index f02716c655a..b4ff343de35 100644 --- a/op-deployer/pkg/deployer/apply.go +++ b/op-deployer/pkg/deployer/apply.go @@ -141,6 +141,9 @@ func ApplyPipeline( opts ApplyPipelineOpts, ) error { intent := opts.Intent + if err := intent.Check(); err != nil { + return err + } st := opts.State progressor := func(curr, total int64) { diff --git a/op-deployer/pkg/deployer/artifacts/locator.go b/op-deployer/pkg/deployer/artifacts/locator.go index aa44d43644c..42b838f66a7 100644 --- a/op-deployer/pkg/deployer/artifacts/locator.go +++ b/op-deployer/pkg/deployer/artifacts/locator.go @@ -70,11 +70,7 @@ func (a *Locator) MarshalText() ([]byte, error) { return []byte(a.URL.String()), nil } - if a.Tag != "" { - return []byte("tag://" + a.Tag), nil - } - - return nil, fmt.Errorf("no URL, path or tag set") + return []byte("tag://" + a.Tag), nil } func (a *Locator) IsTag() bool { diff --git a/op-deployer/pkg/deployer/flags.go b/op-deployer/pkg/deployer/flags.go index 2611957f0ad..a58d35bbbb8 100644 --- a/op-deployer/pkg/deployer/flags.go +++ b/op-deployer/pkg/deployer/flags.go @@ -20,6 +20,7 @@ const ( OutdirFlagName = "outdir" PrivateKeyFlagName = "private-key" DeploymentStrategyFlagName = "deployment-strategy" + IntentConfigTypeFlagName = "intent-config-type" ) var ( @@ -35,7 +36,7 @@ var ( Name: L1ChainIDFlagName, Usage: "Chain ID of the L1 chain.", EnvVars: PrefixEnvVar("L1_CHAIN_ID"), - Value: 900, + Value: 11155111, } L2ChainIDsFlag = &cli.StringFlag{ Name: L2ChainIDsFlagName, @@ -62,6 +63,17 @@ var ( EnvVars: PrefixEnvVar("DEPLOYMENT_STRATEGY"), Value: string(state.DeploymentStrategyLive), } + IntentConfigTypeFlag = &cli.StringFlag{ + Name: IntentConfigTypeFlagName, + Usage: fmt.Sprintf("Intent config type to use. Options: %s (default), %s, %s, %s, %s", + state.IntentConfigTypeStandard, + state.IntentConfigTypeCustom, + state.IntentConfigTypeStrict, + state.IntentConfigTypeStandardOverrides, + state.IntentConfigTypeStrictOverrides), + EnvVars: PrefixEnvVar("INTENT_CONFIG_TYPE"), + Value: string(state.IntentConfigTypeStandard), + } ) var GlobalFlags = append([]cli.Flag{}, oplog.CLIFlags(EnvVarPrefix)...) @@ -71,6 +83,7 @@ var InitFlags = []cli.Flag{ L2ChainIDsFlag, WorkdirFlag, DeploymentStrategyFlag, + IntentConfigTypeFlag, } var ApplyFlags = []cli.Flag{ diff --git a/op-deployer/pkg/deployer/init.go b/op-deployer/pkg/deployer/init.go index 3a8ae27d2ae..deca136558c 100644 --- a/op-deployer/pkg/deployer/init.go +++ b/op-deployer/pkg/deployer/init.go @@ -7,19 +7,17 @@ import ( "path" "strings" - "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" - "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" op_service "github.com/ethereum-optimism/optimism/op-service" - "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v2" ) type InitConfig struct { DeploymentStrategy state.DeploymentStrategy + IntentConfigType state.IntentConfigType L1ChainID uint64 Outdir string L2ChainIDs []common.Hash @@ -51,6 +49,7 @@ func InitCLI() func(ctx *cli.Context) error { l1ChainID := ctx.Uint64(L1ChainIDFlagName) outdir := ctx.String(OutdirFlagName) l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) + intentConfigType := ctx.String(IntentConfigTypeFlagName) if len(l2ChainIDsRaw) == 0 { return fmt.Errorf("must specify at least one L2 chain ID") @@ -68,6 +67,7 @@ func InitCLI() func(ctx *cli.Context) error { err := Init(InitConfig{ DeploymentStrategy: state.DeploymentStrategy(deploymentStrategy), + IntentConfigType: state.IntentConfigType(intentConfigType), L1ChainID: l1ChainID, Outdir: outdir, L2ChainIDs: l2ChainIDs, @@ -86,55 +86,12 @@ func Init(cfg InitConfig) error { return fmt.Errorf("invalid config for init: %w", err) } - intent := &state.Intent{ - DeploymentStrategy: cfg.DeploymentStrategy, - L1ChainID: cfg.L1ChainID, - FundDevAccounts: true, - L1ContractsLocator: artifacts.DefaultL1ContractsLocator, - L2ContractsLocator: artifacts.DefaultL2ContractsLocator, - } - - l1ChainIDBig := intent.L1ChainIDBig() - - dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + intent, err := state.NewIntent(cfg.IntentConfigType, cfg.DeploymentStrategy, cfg.L1ChainID, cfg.L2ChainIDs) if err != nil { - return fmt.Errorf("failed to create dev keys: %w", err) - } - - addrFor := func(key devkeys.Key) common.Address { - // The error below should never happen, so panic if it does. - addr, err := dk.Address(key) - if err != nil { - panic(err) - } - return addr - } - intent.SuperchainRoles = &state.SuperchainRoles{ - ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainIDBig)), - ProtocolVersionsOwner: addrFor(devkeys.SuperchainProtocolVersionsOwner.Key(l1ChainIDBig)), - Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainIDBig)), - } - - for _, l2ChainID := range cfg.L2ChainIDs { - l2ChainIDBig := l2ChainID.Big() - intent.Chains = append(intent.Chains, &state.ChainIntent{ - ID: l2ChainID, - BaseFeeVaultRecipient: addrFor(devkeys.BaseFeeVaultRecipientRole.Key(l2ChainIDBig)), - L1FeeVaultRecipient: addrFor(devkeys.L1FeeVaultRecipientRole.Key(l2ChainIDBig)), - SequencerFeeVaultRecipient: addrFor(devkeys.SequencerFeeVaultRecipientRole.Key(l2ChainIDBig)), - Eip1559Denominator: 50, - Eip1559Elasticity: 6, - Roles: state.ChainRoles{ - L1ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l2ChainIDBig)), - L2ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)), - SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l2ChainIDBig)), - UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l2ChainIDBig)), - Batcher: addrFor(devkeys.BatcherRole.Key(l2ChainIDBig)), - Proposer: addrFor(devkeys.ProposerRole.Key(l2ChainIDBig)), - Challenger: addrFor(devkeys.ChallengerRole.Key(l2ChainIDBig)), - }, - }) + return err } + intent.DeploymentStrategy = cfg.DeploymentStrategy + intent.ConfigType = cfg.IntentConfigType st := &state.State{ Version: 1, diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index 682aaccfbc0..98a5c89b851 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -714,6 +714,7 @@ func newIntent( l2Loc *artifacts.Locator, ) (*state.Intent, *state.State) { intent := &state.Intent{ + ConfigType: state.IntentConfigTypeCustom, DeploymentStrategy: state.DeploymentStrategyLive, L1ChainID: l1ChainID.Uint64(), SuperchainRoles: &state.SuperchainRoles{ @@ -740,8 +741,9 @@ func newChainIntent(t *testing.T, dk *devkeys.MnemonicDevKeys, l1ChainID *big.In BaseFeeVaultRecipient: addrFor(t, dk, devkeys.BaseFeeVaultRecipientRole.Key(l1ChainID)), L1FeeVaultRecipient: addrFor(t, dk, devkeys.L1FeeVaultRecipientRole.Key(l1ChainID)), SequencerFeeVaultRecipient: addrFor(t, dk, devkeys.SequencerFeeVaultRecipientRole.Key(l1ChainID)), - Eip1559Denominator: 50, - Eip1559Elasticity: 6, + Eip1559DenominatorCanyon: standard.Eip1559DenominatorCanyon, + Eip1559Denominator: standard.Eip1559Denominator, + Eip1559Elasticity: standard.Eip1559Elasticity, Roles: state.ChainRoles{ L1ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), L2ProxyAdminOwner: addrFor(t, dk, devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), diff --git a/op-deployer/pkg/deployer/pipeline/init.go b/op-deployer/pkg/deployer/pipeline/init.go index 88caf760f41..f7be4eae03d 100644 --- a/op-deployer/pkg/deployer/pipeline/init.go +++ b/op-deployer/pkg/deployer/pipeline/init.go @@ -141,10 +141,10 @@ func displayWarning() error { ####################### WARNING! WARNING WARNING! ####################### You are deploying a tagged release to a chain with no pre-deployed OPCM. -The contracts you are deploying may not be audited, or match a governance +The contracts you are deploying may not be audited, or match a governance approved release. -USE OF THIS DEPLOYMENT IS NOT RECOMMENDED FOR PRODUCTION. USE AT YOUR OWN +USE OF THIS DEPLOYMENT IS NOT RECOMMENDED FOR PRODUCTION. USE AT YOUR OWN RISK. BUGS OR LOSS OF FUNDS MAY OCCUR. WE HOPE YOU KNOW WHAT YOU ARE DOING. diff --git a/op-deployer/pkg/deployer/standard/standard.go b/op-deployer/pkg/deployer/standard/standard.go index 75902424ac7..d2fe5e5d942 100644 --- a/op-deployer/pkg/deployer/standard/standard.go +++ b/op-deployer/pkg/deployer/standard/standard.go @@ -26,6 +26,9 @@ const ( DisputeSplitDepth uint64 = 30 DisputeClockExtension uint64 = 10800 DisputeMaxClockDuration uint64 = 302400 + Eip1559DenominatorCanyon uint64 = 250 + Eip1559Denominator uint64 = 50 + Eip1559Elasticity uint64 = 6 ContractsV160Tag = "op-contracts/v1.6.0" ContractsV170Beta1L2Tag = "op-contracts/v1.7.0-beta.1+l2-contracts" @@ -97,6 +100,28 @@ func L1VersionsFor(chainID uint64) (L1Versions, error) { } } +func GuardianAddressFor(chainID uint64) (common.Address, error) { + switch chainID { + case 1: + return common.HexToAddress("0x09f7150D8c019BeF34450d6920f6B3608ceFdAf2"), nil + case 11155111: + return common.HexToAddress("0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E"), nil + default: + return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID) + } +} + +func ChallengerAddressFor(chainID uint64) (common.Address, error) { + switch chainID { + case 1: + return common.HexToAddress("0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A"), nil + case 11155111: + return common.HexToAddress("0xfd1D2e729aE8eEe2E146c033bf4400fE75284301"), nil + default: + return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID) + } +} + func SuperchainFor(chainID uint64) (*superchain.Superchain, error) { switch chainID { case 1: @@ -115,7 +140,7 @@ func ChainNameFor(chainID uint64) (string, error) { case 11155111: return "sepolia", nil default: - return "", fmt.Errorf("unrecognized chain ID: %d", chainID) + return "", fmt.Errorf("unrecognized l1 chain ID: %d", chainID) } } @@ -173,6 +198,17 @@ func SystemOwnerAddrFor(chainID uint64) (common.Address, error) { } } +func L1ProxyAdminOwner(chainID uint64) (common.Address, error) { + switch chainID { + case 1: + return common.HexToAddress("0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A"), nil + case 11155111: + return common.HexToAddress("0x1Eb2fFc903729a0F03966B917003800b145F56E2"), nil + default: + return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID) + } +} + func ArtifactsURLForTag(tag string) (*url.URL, error) { switch tag { case "op-contracts/v1.6.0": diff --git a/op-deployer/pkg/deployer/state/chain_intent.go b/op-deployer/pkg/deployer/state/chain_intent.go new file mode 100644 index 00000000000..bb6693f56b8 --- /dev/null +++ b/op-deployer/pkg/deployer/state/chain_intent.go @@ -0,0 +1,82 @@ +package state + +import ( + "fmt" + "reflect" + + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum/go-ethereum/common" +) + +type ChainIntent struct { + ID common.Hash `json:"id" toml:"id"` + BaseFeeVaultRecipient common.Address `json:"baseFeeVaultRecipient" toml:"baseFeeVaultRecipient"` + L1FeeVaultRecipient common.Address `json:"l1FeeVaultRecipient" toml:"l1FeeVaultRecipient"` + SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient" toml:"sequencerFeeVaultRecipient"` + Eip1559DenominatorCanyon uint64 `json:"eip1559DenominatorCanyon" toml:"eip1559DenominatorCanyon"` + Eip1559Denominator uint64 `json:"eip1559Denominator" toml:"eip1559Denominator"` + Eip1559Elasticity uint64 `json:"eip1559Elasticity" toml:"eip1559Elasticity"` + Roles ChainRoles `json:"roles" toml:"roles"` + DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"` + DangerousAltDAConfig genesis.AltDADeployConfig `json:"dangerousAltDAConfig,omitempty" toml:"dangerousAltDAConfig,omitempty"` +} + +type ChainRoles struct { + L1ProxyAdminOwner common.Address `json:"l1ProxyAdminOwner" toml:"l1ProxyAdminOwner"` + L2ProxyAdminOwner common.Address `json:"l2ProxyAdminOwner" toml:"l2ProxyAdminOwner"` + SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"` + UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"` + Batcher common.Address `json:"batcher" toml:"batcher"` + Proposer common.Address `json:"proposer" toml:"proposer"` + Challenger common.Address `json:"challenger" toml:"challenger"` +} + +var ErrChainRoleZeroAddress = fmt.Errorf("ChainRole is set to zero address") +var ErrFeeVaultZeroAddress = fmt.Errorf("chain has a fee vault set to zero address") +var ErrNonStandardValue = fmt.Errorf("chain contains non-standard config value") +var ErrEip1559ZeroValue = fmt.Errorf("eip1559 param is set to zero value") + +func (c *ChainIntent) Check() error { + if c.ID == emptyHash { + return fmt.Errorf("id must be set") + } + + if err := c.Roles.CheckNoZeroAddresses(); err != nil { + return err + } + + if c.Eip1559DenominatorCanyon == 0 || + c.Eip1559Denominator == 0 || + c.Eip1559Elasticity == 0 { + return fmt.Errorf("%w: chainId=%s", ErrEip1559ZeroValue, c.ID) + } + if c.BaseFeeVaultRecipient == emptyAddress || + c.L1FeeVaultRecipient == emptyAddress || + c.SequencerFeeVaultRecipient == emptyAddress { + return fmt.Errorf("%w: chainId=%s", ErrFeeVaultZeroAddress, c.ID) + } + + if c.DangerousAltDAConfig.UseAltDA { + return c.DangerousAltDAConfig.Check(nil) + } + + return nil +} + +// Returns an error if any fields in ChainRoles is set to common.Address{} +func (cr *ChainRoles) CheckNoZeroAddresses() error { + val := reflect.ValueOf(*cr) + typ := reflect.TypeOf(*cr) + + // Iterate through all the fields + for i := 0; i < val.NumField(); i++ { + fieldValue := val.Field(i) + fieldName := typ.Field(i).Name + + if fieldValue.Interface() == (common.Address{}) { + return fmt.Errorf("%w: %s", ErrChainRoleZeroAddress, fieldName) + } + } + + return nil +} diff --git a/op-deployer/pkg/deployer/state/intent.go b/op-deployer/pkg/deployer/state/intent.go index 86e6cfc1ed4..ab76eb4fb4f 100644 --- a/op-deployer/pkg/deployer/state/intent.go +++ b/op-deployer/pkg/deployer/state/intent.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" "math/big" - - "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "net/url" + "reflect" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" @@ -32,63 +32,191 @@ func (d DeploymentStrategy) Check() error { } } +type IntentConfigType string + +const ( + IntentConfigTypeStandard IntentConfigType = "standard" + IntentConfigTypeCustom IntentConfigType = "custom" + IntentConfigTypeStrict IntentConfigType = "strict" + IntentConfigTypeStandardOverrides IntentConfigType = "standard-overrides" + IntentConfigTypeStrictOverrides IntentConfigType = "strict-overrides" +) + var emptyAddress common.Address +var emptyHash common.Hash type Intent struct { - DeploymentStrategy DeploymentStrategy `json:"deploymentStrategy" toml:"deploymentStrategy"` + DeploymentStrategy DeploymentStrategy `json:"deploymentStrategy" toml:"deploymentStrategy"` + ConfigType IntentConfigType `json:"configType" toml:"configType"` + L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"` + SuperchainRoles *SuperchainRoles `json:"superchainRoles" toml:"superchainRoles,omitempty"` + FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` + UseInterop bool `json:"useInterop" toml:"useInterop"` + L1ContractsLocator *artifacts.Locator `json:"l1ContractsLocator" toml:"l1ContractsLocator"` + L2ContractsLocator *artifacts.Locator `json:"l2ContractsLocator" toml:"l2ContractsLocator"` + Chains []*ChainIntent `json:"chains" toml:"chains"` + GlobalDeployOverrides map[string]any `json:"globalDeployOverrides" toml:"globalDeployOverrides"` +} + +type SuperchainRoles struct { + ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` + ProtocolVersionsOwner common.Address `json:"protocolVersionsOwner" toml:"protocolVersionsOwner"` + Guardian common.Address `json:"guardian" toml:"guardian"` +} + +var ErrSuperchainRoleZeroAddress = errors.New("SuperchainRole is set to zero address") +var ErrL1ContractsLocatorUndefined = errors.New("L1ContractsLocator undefined") +var ErrL2ContractsLocatorUndefined = errors.New("L2ContractsLocator undefined") - L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"` +func (s *SuperchainRoles) CheckNoZeroAddresses() error { + val := reflect.ValueOf(*s) + typ := reflect.TypeOf(*s) - SuperchainRoles *SuperchainRoles `json:"superchainRoles" toml:"superchainRoles,omitempty"` + // Iterate through all the fields + for i := 0; i < val.NumField(); i++ { + fieldValue := val.Field(i) + fieldName := typ.Field(i).Name + + if fieldValue.Interface() == (common.Address{}) { + return fmt.Errorf("%w: %s", ErrSuperchainRoleZeroAddress, fieldName) + } + } + return nil +} - FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` +func (c *Intent) L1ChainIDBig() *big.Int { + return big.NewInt(int64(c.L1ChainID)) +} - UseInterop bool `json:"useInterop" toml:"useInterop"` +func (c *Intent) validateCustomConfig() error { + if c.L1ContractsLocator == nil || + (c.L1ContractsLocator.Tag == "" && c.L1ContractsLocator.URL == &url.URL{}) { + return ErrL1ContractsLocatorUndefined + } + if c.L2ContractsLocator == nil || + (c.L2ContractsLocator.Tag == "" && c.L2ContractsLocator.URL == &url.URL{}) { + return ErrL2ContractsLocatorUndefined + } - L1ContractsLocator *artifacts.Locator `json:"l1ContractsLocator" toml:"l1ContractsLocator"` + if err := c.SuperchainRoles.CheckNoZeroAddresses(); err != nil { + return err + } - L2ContractsLocator *artifacts.Locator `json:"l2ContractsLocator" toml:"l2ContractsLocator"` + if len(c.Chains) == 0 { + return errors.New("must define at least one l2 chain") + } - Chains []*ChainIntent `json:"chains" toml:"chains"` + for _, chain := range c.Chains { + if err := chain.Check(); err != nil { + return err + } + } - GlobalDeployOverrides map[string]any `json:"globalDeployOverrides" toml:"globalDeployOverrides"` + return nil } -func (c *Intent) L1ChainIDBig() *big.Int { - return big.NewInt(int64(c.L1ChainID)) +func (c *Intent) validateStrictConfig() error { + if err := c.validateStandardValues(); err != nil { + return err + } + + challenger, _ := standard.ChallengerAddressFor(c.L1ChainID) + l1ProxyAdminOwner, _ := standard.L1ProxyAdminOwner(c.L1ChainID) + for chainIndex := range c.Chains { + if c.Chains[chainIndex].Roles.Challenger != challenger { + return fmt.Errorf("invalid challenger address for chain: %s", c.Chains[chainIndex].ID) + } + if c.Chains[chainIndex].Roles.L1ProxyAdminOwner != l1ProxyAdminOwner { + return fmt.Errorf("invalid l1ProxyAdminOwner address for chain: %s", c.Chains[chainIndex].ID) + } + } + + return nil } -func (c *Intent) Check() error { - if c.DeploymentStrategy != DeploymentStrategyLive && c.DeploymentStrategy != DeploymentStrategyGenesis { - return fmt.Errorf("deploymentStrategy must be 'live' or 'local'") +// Ensures the following: +// 1. no zero-values for non-standard fields (user should have populated these) +// 2. no non-standard values for standard fields (user should not have changed these) +func (c *Intent) validateStandardValues() error { + if err := c.checkL1Prod(); err != nil { + return err + } + if err := c.checkL2Prod(); err != nil { + return err } + standardSuperchainRoles, err := getStandardSuperchainRoles(c.L1ChainID) + if err != nil { + return fmt.Errorf("error getting standard superchain roles: %w", err) + } + if *c.SuperchainRoles != *standardSuperchainRoles { + return fmt.Errorf("SuperchainRoles does not match standard value") + } + + for _, chain := range c.Chains { + if err := chain.Check(); err != nil { + return err + } + if chain.Eip1559DenominatorCanyon != standard.Eip1559DenominatorCanyon || + chain.Eip1559Denominator != standard.Eip1559Denominator || + chain.Eip1559Elasticity != standard.Eip1559Elasticity { + return fmt.Errorf("%w: chainId=%s", ErrNonStandardValue, chain.ID) + } + } + + return nil +} + +func getStandardSuperchainRoles(l1ChainId uint64) (*SuperchainRoles, error) { + superCfg, err := standard.SuperchainFor(l1ChainId) + if err != nil { + return nil, fmt.Errorf("error getting superchain config: %w", err) + } + + proxyAdminOwner, _ := standard.L1ProxyAdminOwner(l1ChainId) + guardian, _ := standard.GuardianAddressFor(l1ChainId) + + superchainRoles := &SuperchainRoles{ + ProxyAdminOwner: proxyAdminOwner, + ProtocolVersionsOwner: common.Address(*superCfg.Config.ProtocolVersionsAddr), + Guardian: guardian, + } + + return superchainRoles, nil +} + +func (c *Intent) Check() error { if c.L1ChainID == 0 { - return fmt.Errorf("l1ChainID must be set") + return fmt.Errorf("l1ChainID cannot be 0") + } + + if err := c.DeploymentStrategy.Check(); err != nil { + return err } if c.L1ContractsLocator == nil { - return errors.New("l1ContractsLocator must be set") + return ErrL1ContractsLocatorUndefined } if c.L2ContractsLocator == nil { - return errors.New("l2ContractsLocator must be set") + return ErrL2ContractsLocatorUndefined } var err error - if c.L1ContractsLocator.IsTag() { - err = c.checkL1Prod() - } else { - err = c.checkL1Dev() + switch c.ConfigType { + case IntentConfigTypeStandard: + err = c.validateStandardValues() + case IntentConfigTypeCustom: + err = c.validateCustomConfig() + case IntentConfigTypeStrict: + err = c.validateStrictConfig() + case IntentConfigTypeStandardOverrides, IntentConfigTypeStrictOverrides: + err = c.validateCustomConfig() + default: + return fmt.Errorf("intent-config-type unsupported: %s", c.ConfigType) } if err != nil { - return err - } - - if c.L2ContractsLocator.IsTag() { - if err := c.checkL2Prod(); err != nil { - return err - } + return fmt.Errorf("failed to validate intent-config-type=%s: %w", c.ConfigType, err) } return nil @@ -121,100 +249,113 @@ func (c *Intent) checkL1Prod() error { return nil } -func (c *Intent) checkL1Dev() error { - if c.SuperchainRoles.ProxyAdminOwner == emptyAddress { - return fmt.Errorf("proxyAdminOwner must be set") - } - - if c.SuperchainRoles.ProtocolVersionsOwner == emptyAddress { - c.SuperchainRoles.ProtocolVersionsOwner = c.SuperchainRoles.ProxyAdminOwner - } - - if c.SuperchainRoles.Guardian == emptyAddress { - c.SuperchainRoles.Guardian = c.SuperchainRoles.ProxyAdminOwner - } - - return nil -} - func (c *Intent) checkL2Prod() error { _, err := standard.ArtifactsURLForTag(c.L2ContractsLocator.Tag) return err } -type SuperchainRoles struct { - ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` - - ProtocolVersionsOwner common.Address `json:"protocolVersionsOwner" toml:"protocolVersionsOwner"` - - Guardian common.Address `json:"guardian" toml:"guardian"` -} - -type ChainIntent struct { - ID common.Hash `json:"id" toml:"id"` - - BaseFeeVaultRecipient common.Address `json:"baseFeeVaultRecipient" toml:"baseFeeVaultRecipient"` - - L1FeeVaultRecipient common.Address `json:"l1FeeVaultRecipient" toml:"l1FeeVaultRecipient"` +func NewIntent(configType IntentConfigType, deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + switch configType { + case IntentConfigTypeCustom: + return NewIntentCustom(deploymentStrategy, l1ChainId, l2ChainIds) - SequencerFeeVaultRecipient common.Address `json:"sequencerFeeVaultRecipient" toml:"sequencerFeeVaultRecipient"` + case IntentConfigTypeStandard: + return NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) - Eip1559Denominator uint64 `json:"eip1559Denominator" toml:"eip1559Denominator"` + case IntentConfigTypeStandardOverrides: + return NewIntentStandardOverrides(deploymentStrategy, l1ChainId, l2ChainIds) - Eip1559Elasticity uint64 `json:"eip1559Elasticity" toml:"eip1559Elasticity"` + case IntentConfigTypeStrict: + return NewIntentStrict(deploymentStrategy, l1ChainId, l2ChainIds) - Roles ChainRoles `json:"roles" toml:"roles"` + case IntentConfigTypeStrictOverrides: + return NewIntentStrictOverrides(deploymentStrategy, l1ChainId, l2ChainIds) - DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"` - - DangerousAltDAConfig genesis.AltDADeployConfig `json:"dangerousAltDAConfig,omitempty" toml:"dangerousAltDAConfig,omitempty"` + default: + return Intent{}, fmt.Errorf("intent config type not supported") + } } -type ChainRoles struct { - L1ProxyAdminOwner common.Address `json:"l1ProxyAdminOwner" toml:"l1ProxyAdminOwner"` - - L2ProxyAdminOwner common.Address `json:"l2ProxyAdminOwner" toml:"l2ProxyAdminOwner"` - - SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"` - - UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"` - - Batcher common.Address `json:"batcher" toml:"batcher"` - - Proposer common.Address `json:"proposer" toml:"proposer"` +// Sets all Intent fields to their zero value with the expectation that the +// user will populate the values before running 'apply' +func NewIntentCustom(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + intent := Intent{ + DeploymentStrategy: deploymentStrategy, + ConfigType: IntentConfigTypeCustom, + L1ChainID: l1ChainId, + L1ContractsLocator: &artifacts.Locator{URL: &url.URL{}}, + L2ContractsLocator: &artifacts.Locator{URL: &url.URL{}}, + SuperchainRoles: &SuperchainRoles{}, + } - Challenger common.Address `json:"challenger" toml:"challenger"` + for _, l2ChainID := range l2ChainIds { + intent.Chains = append(intent.Chains, &ChainIntent{ + ID: l2ChainID, + }) + } + return intent, nil } -func (c *ChainIntent) Check() error { - var emptyHash common.Hash - if c.ID == emptyHash { - return fmt.Errorf("id must be set") +func NewIntentStandard(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + intent := Intent{ + DeploymentStrategy: deploymentStrategy, + ConfigType: IntentConfigTypeStandard, + L1ChainID: l1ChainId, + L1ContractsLocator: artifacts.DefaultL1ContractsLocator, + L2ContractsLocator: artifacts.DefaultL2ContractsLocator, } - if c.Roles.L1ProxyAdminOwner == emptyAddress { - return fmt.Errorf("proxyAdminOwner must be set") + superchainRoles, err := getStandardSuperchainRoles(l1ChainId) + if err != nil { + return Intent{}, fmt.Errorf("error getting standard superchain roles: %w", err) } - - if c.Roles.SystemConfigOwner == emptyAddress { - c.Roles.SystemConfigOwner = c.Roles.L1ProxyAdminOwner + intent.SuperchainRoles = superchainRoles + + for _, l2ChainID := range l2ChainIds { + intent.Chains = append(intent.Chains, &ChainIntent{ + ID: l2ChainID, + Eip1559DenominatorCanyon: standard.Eip1559DenominatorCanyon, + Eip1559Denominator: standard.Eip1559Denominator, + Eip1559Elasticity: standard.Eip1559Elasticity, + }) } + return intent, nil +} - if c.Roles.L2ProxyAdminOwner == emptyAddress { - return fmt.Errorf("l2ProxyAdminOwner must be set") +func NewIntentStandardOverrides(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + intent, err := NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) + if err != nil { + return Intent{}, err } + intent.ConfigType = IntentConfigTypeStandardOverrides - if c.Roles.UnsafeBlockSigner == emptyAddress { - return fmt.Errorf("unsafeBlockSigner must be set") + return intent, nil +} + +// Same as NewIntentStandard, but also sets l2 Challenger and L1ProxyAdminOwner +// addresses to standard values +func NewIntentStrict(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + intent, err := NewIntentStandard(deploymentStrategy, l1ChainId, l2ChainIds) + if err != nil { + return Intent{}, err } + intent.ConfigType = IntentConfigTypeStrict - if c.Roles.Batcher == emptyAddress { - return fmt.Errorf("batcher must be set") + challenger, _ := standard.ChallengerAddressFor(l1ChainId) + l1ProxyAdminOwner, _ := standard.ManagerOwnerAddrFor(l1ChainId) + for chainIndex := range intent.Chains { + intent.Chains[chainIndex].Roles.Challenger = challenger + intent.Chains[chainIndex].Roles.L1ProxyAdminOwner = l1ProxyAdminOwner } + return intent, nil +} - if c.DangerousAltDAConfig.UseAltDA { - return c.DangerousAltDAConfig.Check(nil) +func NewIntentStrictOverrides(deploymentStrategy DeploymentStrategy, l1ChainId uint64, l2ChainIds []common.Hash) (Intent, error) { + intent, err := NewIntentStrict(deploymentStrategy, l1ChainId, l2ChainIds) + if err != nil { + return Intent{}, err } + intent.ConfigType = IntentConfigTypeStrictOverrides - return nil + return intent, nil } diff --git a/op-deployer/pkg/deployer/state/intent_test.go b/op-deployer/pkg/deployer/state/intent_test.go new file mode 100644 index 00000000000..1d8c12375f8 --- /dev/null +++ b/op-deployer/pkg/deployer/state/intent_test.go @@ -0,0 +1,89 @@ +package state + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestValidateStandardValues(t *testing.T) { + intent, err := NewIntentStandard(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")}) + require.NoError(t, err) + + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrChainRoleZeroAddress) + + setChainRoles(&intent) + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrFeeVaultZeroAddress) + + setFeeAddresses(&intent) + err = intent.Check() + require.NoError(t, err) + + intent.Chains[0].Eip1559Denominator = 3 // set to non-standard value + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrNonStandardValue) +} + +func TestValidateCustomValues(t *testing.T) { + intent, err := NewIntentCustom(DeploymentStrategyLive, 1, []common.Hash{common.HexToHash("0x336")}) + require.NoError(t, err) + + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrSuperchainRoleZeroAddress) + + setSuperchainRoles(&intent) + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrChainRoleZeroAddress) + + setChainRoles(&intent) + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrEip1559ZeroValue) + + setEip1559Params(&intent) + err = intent.Check() + require.Error(t, err) + require.ErrorIs(t, err, ErrFeeVaultZeroAddress) + + setFeeAddresses(&intent) + err = intent.Check() + require.NoError(t, err) +} + +func setSuperchainRoles(intent *Intent) { + intent.SuperchainRoles = &SuperchainRoles{ + ProxyAdminOwner: common.HexToAddress("0xa"), + ProtocolVersionsOwner: common.HexToAddress("0xb"), + Guardian: common.HexToAddress("0xc"), + } +} + +func setEip1559Params(intent *Intent) { + intent.Chains[0].Eip1559Denominator = 5000 + intent.Chains[0].Eip1559DenominatorCanyon = 5000 + intent.Chains[0].Eip1559Elasticity = 5000 +} + +func setChainRoles(intent *Intent) { + intent.Chains[0].Roles.L1ProxyAdminOwner = common.HexToAddress("0x01") + intent.Chains[0].Roles.L2ProxyAdminOwner = common.HexToAddress("0x02") + intent.Chains[0].Roles.SystemConfigOwner = common.HexToAddress("0x03") + intent.Chains[0].Roles.UnsafeBlockSigner = common.HexToAddress("0x04") + intent.Chains[0].Roles.Batcher = common.HexToAddress("0x05") + intent.Chains[0].Roles.Proposer = common.HexToAddress("0x06") + intent.Chains[0].Roles.Challenger = common.HexToAddress("0x07") +} + +func setFeeAddresses(intent *Intent) { + intent.Chains[0].BaseFeeVaultRecipient = common.HexToAddress("0x08") + intent.Chains[0].L1FeeVaultRecipient = common.HexToAddress("0x09") + intent.Chains[0].SequencerFeeVaultRecipient = common.HexToAddress("0x0A") +} From 601af96c8285f27c967d3058c7a2311b46544316 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Wed, 27 Nov 2024 13:05:25 -0700 Subject: [PATCH 51/61] op-deployer: Bring back error checking in getStandardSuperchainRoles (#13129) --- op-deployer/pkg/deployer/state/intent.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/op-deployer/pkg/deployer/state/intent.go b/op-deployer/pkg/deployer/state/intent.go index ab76eb4fb4f..067ea5bead6 100644 --- a/op-deployer/pkg/deployer/state/intent.go +++ b/op-deployer/pkg/deployer/state/intent.go @@ -173,8 +173,14 @@ func getStandardSuperchainRoles(l1ChainId uint64) (*SuperchainRoles, error) { return nil, fmt.Errorf("error getting superchain config: %w", err) } - proxyAdminOwner, _ := standard.L1ProxyAdminOwner(l1ChainId) - guardian, _ := standard.GuardianAddressFor(l1ChainId) + proxyAdminOwner, err := standard.L1ProxyAdminOwner(l1ChainId) + if err != nil { + return nil, fmt.Errorf("error getting L1ProxyAdminOwner: %w", err) + } + guardian, err := standard.GuardianAddressFor(l1ChainId) + if err != nil { + return nil, fmt.Errorf("error getting guardian address: %w", err) + } superchainRoles := &SuperchainRoles{ ProxyAdminOwner: proxyAdminOwner, From 2bbfd5dc783dff57cb42f4da8c971c5f1db4204d Mon Sep 17 00:00:00 2001 From: Inphi Date: Wed, 27 Nov 2024 12:55:13 -0800 Subject: [PATCH 52/61] make: Remove unused install-geth target (#13130) --- Makefile | 11 ----------- op-e2e/README.md | 1 - 2 files changed, 12 deletions(-) diff --git a/Makefile b/Makefile index 9830a3060cb..4ea83bab36e 100644 --- a/Makefile +++ b/Makefile @@ -173,9 +173,6 @@ nuke: clean devnet-clean ## Completely clean the project directory ## Prepares for running a local devnet pre-devnet: submodules $(DEVNET_CANNON_PRESTATE_FILES) - @if ! [ -x "$$(command -v geth)" ]; then \ - make install-geth; \ - fi @if ! [ -x "$$(command -v eth2-testnet-genesis)" ]; then \ make install-eth2-testnet-genesis; \ fi @@ -247,14 +244,6 @@ update-op-geth: ## Updates the Geth version used in the project ./ops/scripts/update-op-geth.py .PHONY: update-op-geth -install-geth: ## Installs or updates Geth if versions do not match - ./ops/scripts/geth-version-checker.sh && \ - (echo "Geth versions match, not installing geth..."; true) || \ - (echo "Versions do not match, installing geth!"; \ - go install -v github.com/ethereum/go-ethereum/cmd/geth@$(shell jq -r .geth < versions.json); \ - echo "Installed geth!"; true) -.PHONY: install-geth - install-eth2-testnet-genesis: go install -v github.com/protolambda/eth2-testnet-genesis@$(shell jq -r .eth2_testnet_genesis < versions.json) .PHONY: install-eth2-testnet-genesis diff --git a/op-e2e/README.md b/op-e2e/README.md index d6f09619422..a52eaab6325 100644 --- a/op-e2e/README.md +++ b/op-e2e/README.md @@ -5,7 +5,6 @@ created with the `bedrock-devnet` package. To create this state, run the following commands from the root of the repository: ```bash -make install-geth make cannon-prestate make devnet-allocs ``` From cf13a17a06c22e1882b94d5a7e567912af6c5555 Mon Sep 17 00:00:00 2001 From: Yann Hodique Date: Wed, 27 Nov 2024 22:07:37 +0100 Subject: [PATCH 53/61] build: migrate op-node and op-proposer to just (#13042) * build(just): factor out flags code This will enable making use of JUSTFLAGS in the main Makefile for migrated targets. * fix(just): parallel support For some unclear reason runs in CI environment are invalid (they generate some "empty" calls to the private target). Sidestep the issue for now. * build(just): add more helpers - VERSION_META variable - go_generate target * build(op-proposer): migrate build to just * build(op-node): migrate build to just * fix(build): rewire just-migrated targets --------- Co-authored-by: Matthew Slipper --- Makefile | 9 ++++-- just/default.just | 5 ++-- just/deprecated.mk | 34 ++++++----------------- just/flags.mk | 24 ++++++++++++++++ just/git.just | 2 ++ just/go.just | 4 +++ op-batcher/justfile | 19 +++++++------ op-node/Makefile | 66 ++------------------------------------------ op-node/justfile | 49 ++++++++++++++++++++++++++++++++ op-proposer/Makefile | 35 ++--------------------- op-proposer/justfile | 20 ++++++++++++++ 11 files changed, 130 insertions(+), 137 deletions(-) create mode 100644 just/flags.mk create mode 100644 op-node/justfile create mode 100644 op-proposer/justfile diff --git a/Makefile b/Makefile index 4ea83bab36e..4c901d2158a 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +# provide JUSTFLAGS for just-backed targets +include ./just/flags.mk + COMPOSEFLAGS=-d ITESTS_L2_HOST=http://localhost:9545 BEDROCK_TAGS_REMOTE?=origin @@ -94,7 +97,7 @@ submodules: ## Updates git submodules op-node: ## Builds op-node binary - make -C ./op-node op-node + just $(JUSTFLAGS) ./op-node/op-node .PHONY: op-node generate-mocks-op-node: ## Generates mocks for op-node @@ -106,11 +109,11 @@ generate-mocks-op-service: ## Generates mocks for op-service .PHONY: generate-mocks-op-service op-batcher: ## Builds op-batcher binary - make -C ./op-batcher op-batcher + just $(JUSTFLAGS) ./op-batcher/op-batcher .PHONY: op-batcher op-proposer: ## Builds op-proposer binary - make -C ./op-proposer op-proposer + just $(JUSTFLAGS) ./op-proposer/op-proposer .PHONY: op-proposer op-challenger: ## Builds op-challenger binary diff --git a/just/default.just b/just/default.just index 220c27dca5c..92503b23ba5 100644 --- a/just/default.just +++ b/just/default.just @@ -1,5 +1,6 @@ set shell := ["bash", "-c"] -PARALLEL := num_cpus() +PARALLEL_JOBS := num_cpus() -MAP_JUST := "/usr/bin/env -S parallel --shebang --jobs " + PARALLEL + " --colsep ' ' -r " + just_executable() +# TODO: this fails in CI for some reason +MAP_JUST := "/usr/bin/env -S parallel --shebang --jobs " + PARALLEL_JOBS + " --colsep ' ' -r " + just_executable() diff --git a/just/deprecated.mk b/just/deprecated.mk index a18d665c054..655f901348d 100644 --- a/just/deprecated.mk +++ b/just/deprecated.mk @@ -1,42 +1,24 @@ ifeq (, $(shell which tput)) # CI environment typically does not support tput. banner-style = $1 +else ifeq (, $(TERM)) + # Terminal type not set, so tput would fail. + banner-style = $1 else # print in bold red to bring attention. banner-style = $(shell tput bold)$(shell tput setaf 1)$1$(shell tput sgr0) endif -# Variable assignments can affect the semantic of the make targets. -# Typical use-case: setting VERSION in a release build, since CI -# doesn't preserve the git environment. -# -# We need to translate: -# "make target VAR=val" to "just VAR=val target" -# -# MAKEFLAGS is a string of the form: -# "abc --foo --bar=baz -- VAR1=val1 VAR2=val2", namely: -# - abc is the concatnation of all short flags -# - --foo and --bar=baz are long options, -# - -- is the separator between flags and variable assignments, -# - VAR1=val1 and VAR2=val2 are variable assignments -# -# Goal: ignore all CLI flags, keep only variable assignments. -# -# First remove the short flags at the beginning, or the first long-flag, -# or if there is no flag at all, the -- separator (which then makes the -# next step a noop). If there's no flag and no variable assignment, the -# result is empty anyway, so the wordlist call is safe (everything is a noop). -tmp-flags = $(wordlist 2,$(words $(MAKEFLAGS)),$(MAKEFLAGS)) -# Then remove all long options, including the -- separator, if needed. That -# leaves only variable assignments. -just-flags = $(patsubst --%,,$(tmp-flags)) +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(SELF_DIR)/flags.mk define make-deprecated-target $1: @echo - @printf %s\\n '$(call banner-style,"make $1 $(just-flags)" is deprecated. Please use "just $(just-flags) $1" instead.)' + @printf %s\\n '$(call banner-style,Deprecated make call: make $1 $(JUSTFLAGS))' + @printf %s\\n '$(call banner-style,Consider using just instead: just $(JUSTFLAGS) $1)' @echo - just $(just-flags) $1 + just $(JUSTFLAGS) $1 endef $(foreach element,$(DEPRECATED_TARGETS),$(eval $(call make-deprecated-target,$(element)))) diff --git a/just/flags.mk b/just/flags.mk new file mode 100644 index 00000000000..121a3eb70e9 --- /dev/null +++ b/just/flags.mk @@ -0,0 +1,24 @@ +# Variable assignments can affect the semantic of the make targets. +# Typical use-case: setting VERSION in a release build, since CI +# doesn't preserve the git environment. +# +# We need to translate: +# "make target VAR=val" to "just VAR=val target" +# +# MAKEFLAGS is a string of the form: +# "abc --foo --bar=baz -- VAR1=val1 VAR2=val2", namely: +# - abc is the concatnation of all short flags +# - --foo and --bar=baz are long options, +# - -- is the separator between flags and variable assignments, +# - VAR1=val1 and VAR2=val2 are variable assignments +# +# Goal: ignore all CLI flags, keep only variable assignments. +# +# First remove the short flags at the beginning, or the first long-flag, +# or if there is no flag at all, the -- separator (which then makes the +# next step a noop). If there's no flag and no variable assignment, the +# result is empty anyway, so the wordlist call is safe (everything is a noop). +tmp-flags := $(wordlist 2,$(words $(MAKEFLAGS)),$(MAKEFLAGS)) +# Then remove all long options, including the -- separator, if needed. That +# leaves only variable assignments. +JUSTFLAGS := $(patsubst --%,,$(tmp-flags)) \ No newline at end of file diff --git a/just/git.just b/just/git.just index 922286d7ab5..ac50e4e762d 100644 --- a/just/git.just +++ b/just/git.just @@ -24,3 +24,5 @@ VERSION := shell('if [ -z "$1" ]; then else echo $1 fi', _PREFERRED_TAG, _LAST_TAG) + +VERSION_META := "" diff --git a/just/go.just b/just/go.just index 5af76629509..3a394e3ec94 100644 --- a/just/go.just +++ b/just/go.just @@ -25,3 +25,7 @@ go_test SELECTOR *FLAGS: [private] go_fuzz FUZZ TIME='10s' PKG='': (go_test PKG _EXTRALDFLAGS "-fuzztime" TIME "-fuzz" FUZZ "-run" "NOTAREALTEST") + +[private] +go_generate SELECTOR *FLAGS: + go generate -v {{FLAGS}} {{SELECTOR}} \ No newline at end of file diff --git a/op-batcher/justfile b/op-batcher/justfile index 2647debbcb4..a0c671ebd28 100644 --- a/op-batcher/justfile +++ b/op-batcher/justfile @@ -24,12 +24,13 @@ batcher_fuzz_task FUZZ TIME='10s': (go_fuzz FUZZ TIME "./batcher") # Run fuzzing tests fuzz: - #!{{MAP_JUST}} batcher_fuzz_task - FuzzChannelConfig_CheckTimeout - FuzzDurationZero - FuzzDurationTimeoutMaxChannelDuration - FuzzDurationTimeoutZeroMaxChannelDuration - FuzzChannelCloseTimeout - FuzzChannelZeroCloseTimeout - FuzzSeqWindowClose - FuzzSeqWindowZeroTimeoutClose + printf "%s\n" \ + "FuzzChannelConfig_CheckTimeout" \ + "FuzzDurationZero" \ + "FuzzDurationTimeoutMaxChannelDuration" \ + "FuzzDurationTimeoutZeroMaxChannelDuration" \ + "FuzzChannelCloseTimeout" \ + "FuzzChannelZeroCloseTimeout" \ + "FuzzSeqWindowClose" \ + "FuzzSeqWindowZeroTimeoutClose" \ + | parallel -j {{PARALLEL_JOBS}} {{just_executable()}} batcher_fuzz_task {} diff --git a/op-node/Makefile b/op-node/Makefile index c1d480d9b71..b63f489925a 100644 --- a/op-node/Makefile +++ b/op-node/Makefile @@ -1,65 +1,3 @@ -GITCOMMIT ?= $(shell git rev-parse HEAD) -GITDATE ?= $(shell git show -s --format='%ct') -# Find the github tag that points to this commit. If none are found, set the version string to "untagged" -# Prioritizes release tag, if one exists, over tags suffixed with "-rc" -VERSION ?= $(shell tags=$$(git tag --points-at $(GITCOMMIT) | grep '^op-node/' | sed 's/op-node\///' | sort -V); \ - preferred_tag=$$(echo "$$tags" | grep -v -- '-rc' | tail -n 1); \ - if [ -z "$$preferred_tag" ]; then \ - if [ -z "$$tags" ]; then \ - echo "untagged"; \ - else \ - echo "$$tags" | tail -n 1; \ - fi \ - else \ - echo $$preferred_tag; \ - fi) +DEPRECATED_TARGETS := op-node clean test fuzz generate-mocks readme -LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) -LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-node/version.Version=$(VERSION) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-node/version.Meta=$(VERSION_META) -LDFLAGS := -ldflags "$(LDFLAGSSTRING)" - -# Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 -ifeq ($(shell uname),Darwin) - FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic -endif - -op-node: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) CGO_ENABLED=0 go build -v $(LDFLAGS) -o ./bin/op-node ./cmd/main.go - -clean: - rm bin/op-node - -test: - go test -v ./... - -fuzz: - printf "%s\n" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoBedrockRoundTrip ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoEcotoneRoundTrip ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzL1InfoAgainstContract ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzUnmarshallLogEvent ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseFrames ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzFrameUnmarshalBinary ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzBatchRoundTrip ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDeriveDepositsRoundTrip ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDeriveDepositsBadVersion ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseL1InfoDepositTxDataValid ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseL1InfoDepositTxDataBadLength ./rollup/derive" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzRejectCreateBlockBadTimestamp ./rollup/driver" \ - "go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDecodeDepositTxDataToL1Info ./rollup/driver" \ - | parallel -j 8 {} - -generate-mocks: - go generate ./... - -readme: - doctoc README.md - -.PHONY: \ - op-node \ - clean \ - test \ - fuzz \ - readme +include ../just/deprecated.mk diff --git a/op-node/justfile b/op-node/justfile new file mode 100644 index 00000000000..46aadcc84b3 --- /dev/null +++ b/op-node/justfile @@ -0,0 +1,49 @@ +import '../just/go.just' + +# Build ldflags string +_LDFLAGSSTRING := "'" + trim( + "-X main.GitCommit=" + GITCOMMIT + " " + \ + "-X main.GitDate=" + GITDATE + " " + \ + "-X github.com/ethereum-optimism/optimism/op-node/version.Version=" + VERSION + " " + \ + "-X github.com/ethereum-optimism/optimism/op-node/version.Meta=" + VERSION_META + " " + \ + "") + "'" + +BINARY := "./bin/op-node" + +# Build op-node binary +op-node: (go_build BINARY "./cmd" "-ldflags" _LDFLAGSSTRING) + +# Clean build artifacts +clean: + rm -f {{BINARY}} + +# Run tests +test: (go_test "./...") + +# Generate mocks +generate-mocks: (go_generate "./...") + +# Update readme +readme: + doctoc README.md + +[private] +node_fuzz_task FUZZ TIME='10s': (go_fuzz FUZZ TIME "./rollup/derive") + +# Run fuzz tests +fuzz: + printf "%s\n" \ + "FuzzL1InfoBedrockRoundTrip" \ + "FuzzL1InfoEcotoneRoundTrip" \ + "FuzzL1InfoAgainstContract" \ + "FuzzUnmarshallLogEvent" \ + "FuzzParseFrames" \ + "FuzzFrameUnmarshalBinary" \ + "FuzzBatchRoundTrip" \ + "FuzzDeriveDepositsRoundTrip" \ + "FuzzDeriveDepositsBadVersion" \ + "FuzzParseL1InfoDepositTxDataValid" \ + "FuzzParseL1InfoDepositTxDataBadLength" \ + "FuzzRejectCreateBlockBadTimestamp" \ + "FuzzDecodeDepositTxDataToL1Info" \ + | parallel -j {{PARALLEL_JOBS}} {{just_executable()}} node_fuzz_task {} diff --git a/op-proposer/Makefile b/op-proposer/Makefile index 561d7d32f30..3a036e6d5d5 100644 --- a/op-proposer/Makefile +++ b/op-proposer/Makefile @@ -1,34 +1,3 @@ -GITCOMMIT ?= $(shell git rev-parse HEAD) -GITDATE ?= $(shell git show -s --format='%ct') -# Find the github tag that points to this commit. If none are found, set the version string to "untagged" -# Prioritizes release tag, if one exists, over tags suffixed with "-rc" -VERSION ?= $(shell tags=$$(git tag --points-at $(GITCOMMIT) | grep '^op-proposer/' | sed 's/op-proposer\///' | sort -V); \ - preferred_tag=$$(echo "$$tags" | grep -v -- '-rc' | tail -n 1); \ - if [ -z "$$preferred_tag" ]; then \ - if [ -z "$$tags" ]; then \ - echo "untagged"; \ - else \ - echo "$$tags" | tail -n 1; \ - fi \ - else \ - echo $$preferred_tag; \ - fi) +DEPRECATED_TARGETS := op-proposer clean test -LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) -LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) -LDFLAGSSTRING +=-X main.Version=$(VERSION) -LDFLAGS := -ldflags "$(LDFLAGSSTRING)" - -op-proposer: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) CGO_ENABLED=0 go build -v $(LDFLAGS) -o ./bin/op-proposer ./cmd - -clean: - rm bin/op-proposer - -test: - go test -v ./... - -.PHONY: \ - clean \ - op-proposer \ - test +include ../just/deprecated.mk diff --git a/op-proposer/justfile b/op-proposer/justfile new file mode 100644 index 00000000000..08b1b7b7391 --- /dev/null +++ b/op-proposer/justfile @@ -0,0 +1,20 @@ +import '../just/go.just' + +# Build ldflags string +_LDFLAGSSTRING := "'" + trim( + "-X main.GitCommit=" + GITCOMMIT + " " + \ + "-X main.GitDate=" + GITDATE + " " + \ + "-X main.Version=" + VERSION + " " + \ + "") + "'" + +BINARY := "./bin/op-proposer" + +# Build op-proposer binary +op-proposer: (go_build BINARY "./cmd" "-ldflags" _LDFLAGSSTRING) + +# Clean build artifacts +clean: + rm -f {{BINARY}} + +# Run tests +test: (go_test "./...") From af169dbad72fd22dca7aba26adfed133817eb635 Mon Sep 17 00:00:00 2001 From: clabby Date: Wed, 27 Nov 2024 16:08:59 -0500 Subject: [PATCH 54/61] feat(op-deployer): `asterisc` bootstrap CLI (#13113) * feat(op-deployer): `asterisc` bootstrap CLI * rename file * flags * mslipper review * golint --------- Co-authored-by: Matthew Slipper --- .../pkg/deployer/bootstrap/asterisc.go | 185 ++++++++++++++++++ op-deployer/pkg/deployer/bootstrap/flags.go | 13 +- op-deployer/pkg/deployer/opcm/asterisc.go | 64 ++++++ .../pkg/deployer/opcm/asterisc_test.go | 34 ++++ .../scripts/deploy/DeployAsterisc.s.sol | 89 +++++++++ .../src/vendor/asterisc/interfaces/IRISCV.sol | 14 ++ 6 files changed, 397 insertions(+), 2 deletions(-) create mode 100644 op-deployer/pkg/deployer/bootstrap/asterisc.go create mode 100644 op-deployer/pkg/deployer/opcm/asterisc.go create mode 100644 op-deployer/pkg/deployer/opcm/asterisc_test.go create mode 100644 packages/contracts-bedrock/scripts/deploy/DeployAsterisc.s.sol create mode 100644 packages/contracts-bedrock/src/vendor/asterisc/interfaces/IRISCV.sol diff --git a/op-deployer/pkg/deployer/bootstrap/asterisc.go b/op-deployer/pkg/deployer/bootstrap/asterisc.go new file mode 100644 index 00000000000..bad2b5ebbb1 --- /dev/null +++ b/op-deployer/pkg/deployer/bootstrap/asterisc.go @@ -0,0 +1,185 @@ +package bootstrap + +import ( + "context" + "crypto/ecdsa" + "fmt" + "strings" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum-optimism/optimism/op-chain-ops/script/forking" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts" + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/env" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/urfave/cli/v2" +) + +type AsteriscConfig struct { + L1RPCUrl string + PrivateKey string + Logger log.Logger + ArtifactsLocator *artifacts.Locator + + privateKeyECDSA *ecdsa.PrivateKey + + PreimageOracle common.Address +} + +func (c *AsteriscConfig) Check() error { + if c.L1RPCUrl == "" { + return fmt.Errorf("l1RPCUrl must be specified") + } + + if c.PrivateKey == "" { + return fmt.Errorf("private key must be specified") + } + + privECDSA, err := crypto.HexToECDSA(strings.TrimPrefix(c.PrivateKey, "0x")) + if err != nil { + return fmt.Errorf("failed to parse private key: %w", err) + } + c.privateKeyECDSA = privECDSA + + if c.Logger == nil { + return fmt.Errorf("logger must be specified") + } + + if c.ArtifactsLocator == nil { + return fmt.Errorf("artifacts locator must be specified") + } + + if c.PreimageOracle == (common.Address{}) { + return fmt.Errorf("preimage oracle must be specified") + } + + return nil +} + +func AsteriscCLI(cliCtx *cli.Context) error { + logCfg := oplog.ReadCLIConfig(cliCtx) + l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) + oplog.SetGlobalLogHandler(l.Handler()) + + l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName) + privateKey := cliCtx.String(deployer.PrivateKeyFlagName) + artifactsURLStr := cliCtx.String(ArtifactsLocatorFlagName) + artifactsLocator := new(artifacts.Locator) + if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil { + return fmt.Errorf("failed to parse artifacts URL: %w", err) + } + + preimageOracle := common.HexToAddress(cliCtx.String(PreimageOracleFlagName)) + + ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) + + return Asterisc(ctx, AsteriscConfig{ + L1RPCUrl: l1RPCUrl, + PrivateKey: privateKey, + Logger: l, + ArtifactsLocator: artifactsLocator, + PreimageOracle: preimageOracle, + }) +} + +func Asterisc(ctx context.Context, cfg AsteriscConfig) error { + if err := cfg.Check(); err != nil { + return fmt.Errorf("invalid config for Asterisc: %w", err) + } + + lgr := cfg.Logger + progressor := func(curr, total int64) { + lgr.Info("artifacts download progress", "current", curr, "total", total) + } + + artifactsFS, cleanup, err := artifacts.Download(ctx, cfg.ArtifactsLocator, progressor) + if err != nil { + return fmt.Errorf("failed to download artifacts: %w", err) + } + defer func() { + if err := cleanup(); err != nil { + lgr.Warn("failed to clean up artifacts", "err", err) + } + }() + + l1Client, err := ethclient.Dial(cfg.L1RPCUrl) + if err != nil { + return fmt.Errorf("failed to connect to L1 RPC: %w", err) + } + + chainID, err := l1Client.ChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chain ID: %w", err) + } + + signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID)) + chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey) + + bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ + Logger: lgr, + ChainID: chainID, + Client: l1Client, + Signer: signer, + From: chainDeployer, + }) + if err != nil { + return fmt.Errorf("failed to create broadcaster: %w", err) + } + + l1RPC, err := rpc.Dial(cfg.L1RPCUrl) + if err != nil { + return fmt.Errorf("failed to connect to L1 RPC: %w", err) + } + + l1Host, err := env.DefaultScriptHost( + bcaster, + lgr, + chainDeployer, + artifactsFS, + script.WithForkHook(func(cfg *script.ForkConfig) (forking.ForkSource, error) { + src, err := forking.RPCSourceByNumber(cfg.URLOrAlias, l1RPC, *cfg.BlockNumber) + if err != nil { + return nil, fmt.Errorf("failed to create RPC fork source: %w", err) + } + return forking.Cache(src), nil + }), + ) + if err != nil { + return fmt.Errorf("failed to create script host: %w", err) + } + + dgo, err := opcm.DeployAsterisc( + l1Host, + opcm.DeployAsteriscInput{ + PreimageOracle: cfg.PreimageOracle, + }, + ) + if err != nil { + return fmt.Errorf("error deploying asterisc VM: %w", err) + } + + if _, err := bcaster.Broadcast(ctx); err != nil { + return fmt.Errorf("failed to broadcast: %w", err) + } + + lgr.Info("deployed asterisc VM") + + if err := jsonutil.WriteJSON(dgo, ioutil.ToStdOut()); err != nil { + return fmt.Errorf("failed to write output: %w", err) + } + return nil +} diff --git a/op-deployer/pkg/deployer/bootstrap/flags.go b/op-deployer/pkg/deployer/bootstrap/flags.go index b35e96a5f6a..58fb7fc1436 100644 --- a/op-deployer/pkg/deployer/bootstrap/flags.go +++ b/op-deployer/pkg/deployer/bootstrap/flags.go @@ -194,14 +194,17 @@ var DisputeGameFlags = []cli.Flag{ ChallengerFlag, } -var MIPSFlags = []cli.Flag{ +var BaseFPVMFlags = []cli.Flag{ deployer.L1RPCURLFlag, deployer.PrivateKeyFlag, ArtifactsLocatorFlag, PreimageOracleFlag, - MIPSVersionFlag, } +var MIPSFlags = append(BaseFPVMFlags, MIPSVersionFlag) + +var AsteriscFlags = BaseFPVMFlags + var Commands = []*cli.Command{ { Name: "opcm", @@ -227,4 +230,10 @@ var Commands = []*cli.Command{ Flags: cliapp.ProtectFlags(MIPSFlags), Action: MIPSCLI, }, + { + Name: "asterisc", + Usage: "Bootstrap an instance of Asterisc.", + Flags: cliapp.ProtectFlags(AsteriscFlags), + Action: AsteriscCLI, + }, } diff --git a/op-deployer/pkg/deployer/opcm/asterisc.go b/op-deployer/pkg/deployer/opcm/asterisc.go new file mode 100644 index 00000000000..9ba8959e354 --- /dev/null +++ b/op-deployer/pkg/deployer/opcm/asterisc.go @@ -0,0 +1,64 @@ +package opcm + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +type DeployAsteriscInput struct { + PreimageOracle common.Address +} + +func (input *DeployAsteriscInput) InputSet() bool { + return true +} + +type DeployAsteriscOutput struct { + AsteriscSingleton common.Address +} + +func (output *DeployAsteriscOutput) CheckOutput(input common.Address) error { + return nil +} + +type DeployAsteriscScript struct { + Run func(input, output common.Address) error +} + +func DeployAsterisc( + host *script.Host, + input DeployAsteriscInput, +) (DeployAsteriscOutput, error) { + var output DeployAsteriscOutput + inputAddr := host.NewScriptAddress() + outputAddr := host.NewScriptAddress() + + cleanupInput, err := script.WithPrecompileAtAddress[*DeployAsteriscInput](host, inputAddr, &input) + if err != nil { + return output, fmt.Errorf("failed to insert DeployAsteriscInput precompile: %w", err) + } + defer cleanupInput() + + cleanupOutput, err := script.WithPrecompileAtAddress[*DeployAsteriscOutput](host, outputAddr, &output, + script.WithFieldSetter[*DeployAsteriscOutput]) + if err != nil { + return output, fmt.Errorf("failed to insert DeployAsteriscOutput precompile: %w", err) + } + defer cleanupOutput() + + implContract := "DeployAsterisc" + deployScript, cleanupDeploy, err := script.WithScript[DeployAsteriscScript](host, "DeployAsterisc.s.sol", implContract) + if err != nil { + return output, fmt.Errorf("failed to load %s script: %w", implContract, err) + } + defer cleanupDeploy() + + if err := deployScript.Run(inputAddr, outputAddr); err != nil { + return output, fmt.Errorf("failed to run %s script: %w", implContract, err) + } + + return output, nil +} diff --git a/op-deployer/pkg/deployer/opcm/asterisc_test.go b/op-deployer/pkg/deployer/opcm/asterisc_test.go new file mode 100644 index 00000000000..0ed68f7aeaf --- /dev/null +++ b/op-deployer/pkg/deployer/opcm/asterisc_test.go @@ -0,0 +1,34 @@ +package opcm + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil" + "github.com/ethereum-optimism/optimism/op-deployer/pkg/env" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestDeployAsterisc(t *testing.T) { + _, artifacts := testutil.LocalArtifacts(t) + + host, err := env.DefaultScriptHost( + broadcaster.NoopBroadcaster(), + testlog.Logger(t, log.LevelInfo), + common.Address{'D'}, + artifacts, + ) + require.NoError(t, err) + + input := DeployAsteriscInput{ + PreimageOracle: common.Address{0xab}, + } + + output, err := DeployAsterisc(host, input) + require.NoError(t, err) + + require.NotEmpty(t, output.AsteriscSingleton) +} diff --git a/packages/contracts-bedrock/scripts/deploy/DeployAsterisc.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployAsterisc.s.sol new file mode 100644 index 00000000000..09601eb0d8e --- /dev/null +++ b/packages/contracts-bedrock/scripts/deploy/DeployAsterisc.s.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +// Forge +import { Script } from "forge-std/Script.sol"; + +// Scripts +import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol"; +import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; + +// Interfaces +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; +import { IRISCV } from "src/vendor/asterisc/interfaces/IRISCV.sol"; + +/// @title DeployAsteriscInput +contract DeployAsteriscInput is BaseDeployIO { + // Specify the PreimageOracle to use + address internal _preimageOracle; + + function set(bytes4 _sel, address _value) public { + if (_sel == this.preimageOracle.selector) { + require(_value != address(0), "DeployAsterisc: preimageOracle cannot be empty"); + _preimageOracle = _value; + } else { + revert("DeployAsterisc: unknown selector"); + } + } + + function preimageOracle() public view returns (address) { + require(_preimageOracle != address(0), "DeployAsterisc: preimageOracle not set"); + return _preimageOracle; + } +} + +/// @title DeployAsteriscOutput +contract DeployAsteriscOutput is BaseDeployIO { + IRISCV internal _asteriscSingleton; + + function set(bytes4 _sel, address _value) public { + if (_sel == this.asteriscSingleton.selector) { + require(_value != address(0), "DeployAsterisc: asteriscSingleton cannot be zero address"); + _asteriscSingleton = IRISCV(_value); + } else { + revert("DeployAsterisc: unknown selector"); + } + } + + function checkOutput(DeployAsteriscInput _mi) public view { + DeployUtils.assertValidContractAddress(address(_asteriscSingleton)); + assertValidDeploy(_mi); + } + + function asteriscSingleton() public view returns (IRISCV) { + DeployUtils.assertValidContractAddress(address(_asteriscSingleton)); + return _asteriscSingleton; + } + + function assertValidDeploy(DeployAsteriscInput _mi) public view { + assertValidAsteriscSingleton(_mi); + } + + function assertValidAsteriscSingleton(DeployAsteriscInput _mi) internal view { + IRISCV asterisc = asteriscSingleton(); + + require(address(asterisc.oracle()) == address(_mi.preimageOracle()), "ASTERISC-10"); + } +} + +/// @title DeployAsterisc +contract DeployAsterisc is Script { + function run(DeployAsteriscInput _mi, DeployAsteriscOutput _mo) public { + DeployAsteriscSingleton(_mi, _mo); + _mo.checkOutput(_mi); + } + + function DeployAsteriscSingleton(DeployAsteriscInput _mi, DeployAsteriscOutput _mo) internal { + IPreimageOracle preimageOracle = IPreimageOracle(_mi.preimageOracle()); + vm.broadcast(msg.sender); + IRISCV singleton = IRISCV( + DeployUtils.create1({ + _name: "RISCV", + _args: DeployUtils.encodeConstructor(abi.encodeCall(IRISCV.__constructor__, (preimageOracle))) + }) + ); + + vm.label(address(singleton), "AsteriscSingleton"); + _mo.set(_mo.asteriscSingleton.selector, address(singleton)); + } +} diff --git a/packages/contracts-bedrock/src/vendor/asterisc/interfaces/IRISCV.sol b/packages/contracts-bedrock/src/vendor/asterisc/interfaces/IRISCV.sol new file mode 100644 index 00000000000..349694fc876 --- /dev/null +++ b/packages/contracts-bedrock/src/vendor/asterisc/interfaces/IRISCV.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; + +/// @title IRISCV +/// @notice Interface for the RISCV contract. +interface IRISCV is ISemver { + function oracle() external view returns (IPreimageOracle); + function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); + + function __constructor__(IPreimageOracle _oracle) external; +} From 451c52b04e924e3dcd8e16436f7cb1032d5bb01a Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 27 Nov 2024 22:24:38 +0100 Subject: [PATCH 55/61] go.mod: update op-geth to include post-validation hook interop test fix (#13132) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3e36ecc8325..7e6f8737d80 100644 --- a/go.mod +++ b/go.mod @@ -250,7 +250,7 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101411.3-rc.1 +replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101411.3-rc.1.0.20241126165630-b84907bf4d95 //replace github.com/ethereum/go-ethereum => ../go-ethereum diff --git a/go.sum b/go.sum index 4302fb00204..d18aff8414a 100644 --- a/go.sum +++ b/go.sum @@ -187,8 +187,8 @@ github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/u github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101411.3-rc.1 h1:iG5pKldU6e3FZaZJEYzG1H3RsTjARRaLF/MmVkb9JhQ= -github.com/ethereum-optimism/op-geth v1.101411.3-rc.1/go.mod h1:zBADVb3+aon0Idb3uEg/1TFpep+Jdkz3ge9SLFDBXOo= +github.com/ethereum-optimism/op-geth v1.101411.3-rc.1.0.20241126165630-b84907bf4d95 h1:4bgr/Y/Vl2lntFvFM6l/W6P8EWLMxAdF5CRnJStHGGI= +github.com/ethereum-optimism/op-geth v1.101411.3-rc.1.0.20241126165630-b84907bf4d95/go.mod h1:zBADVb3+aon0Idb3uEg/1TFpep+Jdkz3ge9SLFDBXOo= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241126105717-d31591e83048 h1:kb220NeqVRRt/XP5JHt3i4zpLsYNCdWMM/0tDnOFk3o= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20241126105717-d31591e83048/go.mod h1:9feO8jcL5OZ1tvRjEfNAHz4Aggvd6373l+ZxmZZAyZs= github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= From 8ee03877c1b1287f3a7cc71ee8302d3022c6a57c Mon Sep 17 00:00:00 2001 From: George Knee Date: Wed, 27 Nov 2024 21:27:30 +0000 Subject: [PATCH 56/61] batcher: fix state inconsistency (#12981) * remove lastStoredBlock and lastL1Tip from BatchSubmitter state We can use the channelManager's state to infer lastStoredBlock. And lastL1Tip is actually unused. * change log line wording * fix typo * remove unecessary method * clean up driver.calculateL2BlockRangeToStore * some typos * tiny tweak --- op-batcher/batcher/channel_manager.go | 8 +++++ op-batcher/batcher/driver.go | 49 ++++++++++----------------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/op-batcher/batcher/channel_manager.go b/op-batcher/batcher/channel_manager.go index 81ee0fb35a5..1da2def78da 100644 --- a/op-batcher/batcher/channel_manager.go +++ b/op-batcher/batcher/channel_manager.go @@ -480,6 +480,7 @@ func (s *channelManager) pruneSafeBlocks(newSafeHead eth.L2BlockRef) { if newSafeHead.Number+1 < oldestBlock.NumberU64() { // This could happen if there was an L1 reorg. + // Or if the sequencer restarted. s.log.Warn("safe head reversed, clearing channel manager state", "oldestBlock", eth.ToBlockID(oldestBlock), "newSafeBlock", newSafeHead) @@ -565,3 +566,10 @@ func (m *channelManager) CheckExpectedProgress(syncStatus eth.SyncStatus) error } return nil } + +func (m *channelManager) LastStoredBlock() eth.BlockID { + if m.blocks.Len() == 0 { + return eth.BlockID{} + } + return eth.ToBlockID(m.blocks[m.blocks.Len()-1]) +} diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 93c1425c58b..58e533becff 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -114,10 +114,6 @@ type BatchSubmitter struct { txpoolState TxPoolState txpoolBlockedBlob bool - // lastStoredBlock is the last block loaded into `state`. If it is empty it should be set to the l2 safe head. - lastStoredBlock eth.BlockID - lastL1Tip eth.L1BlockRef - state *channelManager } @@ -147,7 +143,6 @@ func (l *BatchSubmitter) StartBatchSubmitting() error { l.shutdownCtx, l.cancelShutdownCtx = context.WithCancel(context.Background()) l.killCtx, l.cancelKillCtx = context.WithCancel(context.Background()) l.clearState(l.shutdownCtx) - l.lastStoredBlock = eth.BlockID{} if err := l.waitForL2Genesis(); err != nil { return fmt.Errorf("error waiting for L2 genesis: %w", err) @@ -271,13 +266,11 @@ func (l *BatchSubmitter) loadBlocksIntoState(syncStatus eth.SyncStatus, ctx cont block, err := l.loadBlockIntoState(ctx, i) if errors.Is(err, ErrReorg) { l.Log.Warn("Found L2 reorg", "block_number", i) - l.lastStoredBlock = eth.BlockID{} return err } else if err != nil { l.Log.Warn("Failed to load block into state", "err", err) return err } - l.lastStoredBlock = eth.ToBlockID(block) latestBlock = block } @@ -366,29 +359,31 @@ func (l *BatchSubmitter) getSyncStatus(ctx context.Context) (*eth.SyncStatus, er } // calculateL2BlockRangeToStore determines the range (start,end] that should be loaded into the local state. -// It also takes care of initializing some local state (i.e. will modify l.lastStoredBlock in certain conditions -// as well as garbage collecting blocks which became safe) func (l *BatchSubmitter) calculateL2BlockRangeToStore(syncStatus eth.SyncStatus) (eth.BlockID, eth.BlockID, error) { if syncStatus.HeadL1 == (eth.L1BlockRef{}) { return eth.BlockID{}, eth.BlockID{}, errors.New("empty sync status") } - - // Check last stored to see if it needs to be set on startup OR set if is lagged behind. - // It lagging implies that the op-node processed some batches that were submitted prior to the current instance of the batcher being alive. - if l.lastStoredBlock == (eth.BlockID{}) { - l.Log.Info("Starting batch-submitter work at safe-head", "safe", syncStatus.SafeL2) - l.lastStoredBlock = syncStatus.SafeL2.ID() - } else if l.lastStoredBlock.Number < syncStatus.SafeL2.Number { - l.Log.Warn("Last submitted block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", l.lastStoredBlock, "safe", syncStatus.SafeL2) - l.lastStoredBlock = syncStatus.SafeL2.ID() - } - // Check if we should even attempt to load any blocks. TODO: May not need this check if syncStatus.SafeL2.Number >= syncStatus.UnsafeL2.Number { - return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("L2 safe head(%d) ahead of L2 unsafe head(%d)", syncStatus.SafeL2.Number, syncStatus.UnsafeL2.Number) + return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("L2 safe head(%d) >= L2 unsafe head(%d)", syncStatus.SafeL2.Number, syncStatus.UnsafeL2.Number) + } + + lastStoredBlock := l.state.LastStoredBlock() + start := lastStoredBlock + end := syncStatus.UnsafeL2.ID() + + // Check last stored block to see if it is empty or has lagged behind. + // It lagging implies that the op-node processed some batches that + // were submitted prior to the current instance of the batcher being alive. + if lastStoredBlock == (eth.BlockID{}) { + l.Log.Info("Resuming batch-submitter work at safe-head", "safe", syncStatus.SafeL2) + start = syncStatus.SafeL2.ID() + } else if lastStoredBlock.Number < syncStatus.SafeL2.Number { + l.Log.Warn("Last stored block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", lastStoredBlock, "safe", syncStatus.SafeL2) + start = syncStatus.SafeL2.ID() } - return l.lastStoredBlock, syncStatus.UnsafeL2.ID(), nil + return start, end, nil } // The following things occur: @@ -704,7 +699,7 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t l.Log.Error("Failed to query L1 tip", "err", err) return err } - l.recordL1Tip(l1tip) + l.Metr.RecordLatestL1Block(l1tip) // Collect next transaction data. This pulls data out of the channel, so we need to make sure // to put it back if ever da or txmgr requests fail, by calling l.recordFailedDARequest/recordFailedTx. @@ -886,14 +881,6 @@ func (l *BatchSubmitter) handleReceipt(r txmgr.TxReceipt[txRef]) { } } -func (l *BatchSubmitter) recordL1Tip(l1tip eth.L1BlockRef) { - if l.lastL1Tip == l1tip { - return - } - l.lastL1Tip = l1tip - l.Metr.RecordLatestL1Block(l1tip) -} - func (l *BatchSubmitter) recordFailedDARequest(id txID, err error) { if err != nil { l.Log.Warn("DA request failed", logFields(id, err)...) From 8a32cbaad4715643d3ee791a028b36be174d0cf9 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Thu, 28 Nov 2024 00:06:07 +0100 Subject: [PATCH 57/61] improve merkletrie test cov (#13131) --- .../test/libraries/trie/MerkleTrie.t.sol | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/packages/contracts-bedrock/test/libraries/trie/MerkleTrie.t.sol b/packages/contracts-bedrock/test/libraries/trie/MerkleTrie.t.sol index 781ada34333..e6d04d971db 100644 --- a/packages/contracts-bedrock/test/libraries/trie/MerkleTrie.t.sol +++ b/packages/contracts-bedrock/test/libraries/trie/MerkleTrie.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { MerkleTrie } from "src/libraries/trie/MerkleTrie.sol"; +import { RLPReader } from "src/libraries/rlp/RLPReader.sol"; import { FFIInterface } from "test/setup/FFIInterface.sol"; import "src/libraries/rlp/RLPErrors.sol"; @@ -372,4 +373,143 @@ contract MerkleTrie_get_Test is Test { vm.expectRevert("MerkleTrie: ran out of proof elements"); MerkleTrie.get(key, proof, root); } + + /// @notice Tests that `get` reverts if a proof node has an unknown prefix + function test_get_unknownNodePrefix_reverts(uint8 prefix) external { + // bound it to only have prefixes where the first nibble is >= 4 + prefix = uint8(bound(prefix, 0x40, 0xff)); + // if the first nibble of the prefix is odd, make it even by adding 16 + if (((prefix / 16) % 2) == 1) { + unchecked { + prefix += 16; + } + // bound it again in case it overflowed + prefix = uint8(bound(prefix, 0x40, 0xff)); + } + + MerkleTrieWrapper wrapper = new MerkleTrieWrapper(); + + bytes memory key = abi.encodePacked( + keccak256(abi.encodePacked(bytes32(0xa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c))) + ); + bytes[] memory proof = new bytes[](5); + proof[0] = + hex"f90211a085ed702d58e6a962ad0e785e5c9036e06d878fd065eb9669122447f6aee7957da05badb8cfd5a7493d928614730af6e14eabe2c93fbac93c853dde3270c446309da01de85a57c524ac56a5bd4bed0b0aa7d963e364ad930ea964d0a42631a77ded4da0fe3143892366faeb9fae1117b888263afe0f74e6c73555fee53a604bf7188431a0af2c79f0dddd15d6f62e3fa60d515c44d58444ad3915c7ca4bddb31c8f148d0ca08f37a2f9093a4aee39519f3a06fe4674cc670fbbbd7a5f4eb096310b7bc1fdc9a086bd12d2031d9714130c687e6822250fa24b3147824780bea96cf8a7406c8966a03e42538ba2da8adaa0eca4550ef62de4dabde8ca06b71ac1b276ff31b67a7655a04a439f7eb6a62c77ec921139925af3359f61d16e083076e0e425583289107d7da0c453a51991b5a4c6174ddff77c0b7d9cc86f05ffda6ff523e2365f19797c7a00a06f43b7b9a118264ab4b6c24d7d3de77f39071a298426bfc27180adfca57d590da0032e0db4dcf122d4bdb1d4ec3c5df5fabd3127bcefe412cb046b7f0d80d11c9fa0560c2b8c9466b8cb5ffd600f24ea0ed9838bfdab7870d505d4387c2468d3c498a0597996e939ff8c29c9e59dc47c111e760450a9c4fe2b065825762da2a1f32495a0e3411c9af104364230c49de5a4d0802c84df18beee9778673364e1747a875622a02a6928825356d8280f361a02285af30e73889f4e55ecb63ed85c8581e07061d680"; + proof[1] = + hex"f90211a0db246208c4cef45e9aeb9f1df1baa8572675bc453f7da538165a2bb9e6a4c416a0d26d82a9ddff901d2a1f9e18506120dec0e5b3c95549c5bff0efc355061ea73fa04f1cedbb5c7df7ee5cc3210980baf5537affb29c661c6a4eeb193bc42e7fbc74a0acea389e0cf577d0e13483d98b15c82618ac18b7cc4a479981e3e672ddd16867a0ef59a06aeea1eb5ba1313bbe1fa74ff264d84d7319ab6178213734b5b5efa9c1a08f85dc6001713d77aa4e12982dfdb28fd1c7dcc290d46f2749e8a7d67ba2a694a0f6698ff794881edc50340b75311de64ce3da5f97debcfdfd4d20de57ef3ba7eba0680071ce05e9c7915f731bac8b9673332d1d77ea1f7dadab36d9b233eea32ba4a035ad3686f436232360c2aa364c9f2aa2081318b9fb33cd1050d69ee46f791d62a03b495b3d65d9ae39680a0f835c1d1378d218f7b1fb88d2b2c6ac6ef916f09172a0a808d1e8c632d9a6cfeb3c2c123a58b5b3e1998d4bd02c5fb0f7c5d4ba1338e6a0369376e9152831135ff3a902c9740cf22951d67edd51bf0541565e379d7efc25a0cc26d7fa1c326bc14950e92d9de78e4ed8372ff9727dec34602f24057b3a9b30a0278081783022e748dc70874a72377038935c00c1f0a24bbb8cd0fc208d8b68f4a06c4e83593571b94d08cb78ece0de4920b02a650a47a16583f94c8fe35f724707a0cd7eb9d730e5138fd943200b577e7bbb827d010a50d19af2f4b19ef19658156d80"; + proof[2] = + hex"f90211a0065f58fbe63e8e3387e91047d5b7a4532e7d9de0abc47f04791aef27a140fdb5a0858beea29778551c01b0d3e542d707675856da9c3f1d065c845e55c24d77be89a0e90a410489eff6f4f8d70b0cce1fb1339117ec0f6f1db195a6cc410509a2ebaea078ba7fe504e8d01d57f6bee52c4938d779108e500b5923272441ed2964b8c45da0f0430ed9fa807e5fb6ace75f8766ea60009d8539e00006e359f5f7bc38a76596a0a98a7938db99a2d80abea6349de42bf2576c9e51cc715c85fbacab365ec16f5ba026fadc7d124a456c62ada928eaede3e80611e3e6f99041f7393f062e9e788c8ca0ca48cad1e00d22d6146173341a6060378e738be727a7265a923cf6bfd1f8b610a0f8a4aae21a78ac28e2a61f50396f9a80f6c8232fe4afa203160361c0962242baa09a1029479959fb29b4da7239393fd6ca20bc376d860324f429a51b0e0565a158a0eefb84d3943d680e176258dffe0104ac48c171a8574a811535256a2d8ba531dea062a3d709a2f70ba1970842c4f20a602291273d1f6022e7a14cde2afdcd51e795a0397e6b9b87012cd79cbd0bb7daa4cc43830a673d80b65fb88c0449140175d89ca0f8a4c73c0078cbd32961227910e3f9315bc587716062e39f66be19747ccf9b67a0ea4bdd1b187fdba273a8625f88f284994d19c38ec58651839852665717d953d9a0319ebf356f45da83c7f106f1fd3decbf15f651fad3389a0d279602cdea8ee11480"; + proof[3] = + hex"f8f1a069a092c7a950214e7e45b99012dc8ad112eab0fc94ae5ca9efbd6949068384f280a0b25c46db67ef7cf0c47bb400c31c85a26c5a204431527c964c8ecaf3d63e52cc80a01911a2a74db0d8d182447176e23f25556d1a1eaa0afad96453f2d64876ad88e480808080a04a0ca9e3bed1bc3e3c819384d19b6d5e523164a6520c4eb42e828a63ef730ae38080a03b598ed1b9269d4b05e2e75cfb54298d25437669870c919a59a147d2d256fdba80a0db2d655057c83107a73d086cfdd8fcc74739bb48c652eb0ce597178ecf96b39aa05c66ac392a761341b9c22b773ea19af311f34ef537640b9bb96842ec6ace913280"; + + proof[4] = bytes.concat( + hex"f69f", + bytes1(prefix), + hex"4dcf44e265ba93879b2da89e1b16ab48fc5eb8e31bc16b0612d6da8463f195942536c09e5f5691498805884fa37811be3b2bddb4" + ); + + bytes32 root; + (proof[0], proof[1], proof[2], proof[3], root) = rehashOtherElements(proof[4]); + + vm.expectRevert("MerkleTrie: received a node with an unknown prefix"); + wrapper.get(key, proof, root); + } + + /// @notice Tests that `get` reverts if a proof node is unparsable i.e list length is not 2 or 17 + function test_get_unparsableNode_reverts(uint8 listLen) external { + listLen = uint8(bound(listLen, 1, RLPReader.MAX_LIST_LENGTH)); + if (listLen == 2 || listLen == 17) { + listLen++; + } + + MerkleTrieWrapper wrapper = new MerkleTrieWrapper(); + + bytes memory key = abi.encodePacked( + keccak256(abi.encodePacked(bytes32(0xa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c))) + ); + bytes[] memory proof = new bytes[](5); + proof[0] = + hex"f90211a085ed702d58e6a962ad0e785e5c9036e06d878fd065eb9669122447f6aee7957da05badb8cfd5a7493d928614730af6e14eabe2c93fbac93c853dde3270c446309da01de85a57c524ac56a5bd4bed0b0aa7d963e364ad930ea964d0a42631a77ded4da0fe3143892366faeb9fae1117b888263afe0f74e6c73555fee53a604bf7188431a0af2c79f0dddd15d6f62e3fa60d515c44d58444ad3915c7ca4bddb31c8f148d0ca08f37a2f9093a4aee39519f3a06fe4674cc670fbbbd7a5f4eb096310b7bc1fdc9a086bd12d2031d9714130c687e6822250fa24b3147824780bea96cf8a7406c8966a03e42538ba2da8adaa0eca4550ef62de4dabde8ca06b71ac1b276ff31b67a7655a04a439f7eb6a62c77ec921139925af3359f61d16e083076e0e425583289107d7da0c453a51991b5a4c6174ddff77c0b7d9cc86f05ffda6ff523e2365f19797c7a00a06f43b7b9a118264ab4b6c24d7d3de77f39071a298426bfc27180adfca57d590da0032e0db4dcf122d4bdb1d4ec3c5df5fabd3127bcefe412cb046b7f0d80d11c9fa0560c2b8c9466b8cb5ffd600f24ea0ed9838bfdab7870d505d4387c2468d3c498a0597996e939ff8c29c9e59dc47c111e760450a9c4fe2b065825762da2a1f32495a0e3411c9af104364230c49de5a4d0802c84df18beee9778673364e1747a875622a02a6928825356d8280f361a02285af30e73889f4e55ecb63ed85c8581e07061d680"; + proof[1] = + hex"f90211a0db246208c4cef45e9aeb9f1df1baa8572675bc453f7da538165a2bb9e6a4c416a0d26d82a9ddff901d2a1f9e18506120dec0e5b3c95549c5bff0efc355061ea73fa04f1cedbb5c7df7ee5cc3210980baf5537affb29c661c6a4eeb193bc42e7fbc74a0acea389e0cf577d0e13483d98b15c82618ac18b7cc4a479981e3e672ddd16867a0ef59a06aeea1eb5ba1313bbe1fa74ff264d84d7319ab6178213734b5b5efa9c1a08f85dc6001713d77aa4e12982dfdb28fd1c7dcc290d46f2749e8a7d67ba2a694a0f6698ff794881edc50340b75311de64ce3da5f97debcfdfd4d20de57ef3ba7eba0680071ce05e9c7915f731bac8b9673332d1d77ea1f7dadab36d9b233eea32ba4a035ad3686f436232360c2aa364c9f2aa2081318b9fb33cd1050d69ee46f791d62a03b495b3d65d9ae39680a0f835c1d1378d218f7b1fb88d2b2c6ac6ef916f09172a0a808d1e8c632d9a6cfeb3c2c123a58b5b3e1998d4bd02c5fb0f7c5d4ba1338e6a0369376e9152831135ff3a902c9740cf22951d67edd51bf0541565e379d7efc25a0cc26d7fa1c326bc14950e92d9de78e4ed8372ff9727dec34602f24057b3a9b30a0278081783022e748dc70874a72377038935c00c1f0a24bbb8cd0fc208d8b68f4a06c4e83593571b94d08cb78ece0de4920b02a650a47a16583f94c8fe35f724707a0cd7eb9d730e5138fd943200b577e7bbb827d010a50d19af2f4b19ef19658156d80"; + proof[2] = + hex"f90211a0065f58fbe63e8e3387e91047d5b7a4532e7d9de0abc47f04791aef27a140fdb5a0858beea29778551c01b0d3e542d707675856da9c3f1d065c845e55c24d77be89a0e90a410489eff6f4f8d70b0cce1fb1339117ec0f6f1db195a6cc410509a2ebaea078ba7fe504e8d01d57f6bee52c4938d779108e500b5923272441ed2964b8c45da0f0430ed9fa807e5fb6ace75f8766ea60009d8539e00006e359f5f7bc38a76596a0a98a7938db99a2d80abea6349de42bf2576c9e51cc715c85fbacab365ec16f5ba026fadc7d124a456c62ada928eaede3e80611e3e6f99041f7393f062e9e788c8ca0ca48cad1e00d22d6146173341a6060378e738be727a7265a923cf6bfd1f8b610a0f8a4aae21a78ac28e2a61f50396f9a80f6c8232fe4afa203160361c0962242baa09a1029479959fb29b4da7239393fd6ca20bc376d860324f429a51b0e0565a158a0eefb84d3943d680e176258dffe0104ac48c171a8574a811535256a2d8ba531dea062a3d709a2f70ba1970842c4f20a602291273d1f6022e7a14cde2afdcd51e795a0397e6b9b87012cd79cbd0bb7daa4cc43830a673d80b65fb88c0449140175d89ca0f8a4c73c0078cbd32961227910e3f9315bc587716062e39f66be19747ccf9b67a0ea4bdd1b187fdba273a8625f88f284994d19c38ec58651839852665717d953d9a0319ebf356f45da83c7f106f1fd3decbf15f651fad3389a0d279602cdea8ee11480"; + proof[3] = + hex"f8f1a069a092c7a950214e7e45b99012dc8ad112eab0fc94ae5ca9efbd6949068384f280a0b25c46db67ef7cf0c47bb400c31c85a26c5a204431527c964c8ecaf3d63e52cc80a01911a2a74db0d8d182447176e23f25556d1a1eaa0afad96453f2d64876ad88e480808080a04a0ca9e3bed1bc3e3c819384d19b6d5e523164a6520c4eb42e828a63ef730ae38080a03b598ed1b9269d4b05e2e75cfb54298d25437669870c919a59a147d2d256fdba80a0db2d655057c83107a73d086cfdd8fcc74739bb48c652eb0ce597178ecf96b39aa05c66ac392a761341b9c22b773ea19af311f34ef537640b9bb96842ec6ace913280"; + proof[4] = + hex"f69f204dcf44e265ba93879b2da89e1b16ab48fc5eb8e31bc16b0612d6da8463f195942536c09e5f5691498805884fa37811be3b2bddb4"; // Correct + // leaf node + + bytes32 root = keccak256(proof[0]); + + // Should not revert + wrapper.get(key, proof, root); + + if (listLen > 3) { + // Node with list > 3 + proof[4] = + hex"f8379f204dcf44e265ba93879b2da89e1b16ab48fc5eb8e31bc16b0612d6da8463f195942536c09e5f5691498805884fa37811be3b2bddb480"; + for (uint256 i; i < listLen - 3; i++) { + proof[4] = bytes.concat(proof[4], hex"80"); + } + proof[4][1] = bytes1(uint8(proof[4][1]) + (listLen - 3)); + // rehash all proof elements and insert it into the proof element above it + (proof[0], proof[1], proof[2], proof[3], root) = rehashOtherElements(proof[4]); + + vm.expectRevert("MerkleTrie: received an unparseable node"); + wrapper.get(key, proof, root); + } else if (listLen == 1) { + // Node with list of 1 + proof[4] = hex"e09f204dcf44e265ba93879b2da89e1b16ab48fc5eb8e31bc16b0612d6da8463f1"; + // rehash all proof elements and insert it into the proof element above it + (proof[0], proof[1], proof[2], proof[3], root) = rehashOtherElements(proof[4]); + + vm.expectRevert("MerkleTrie: received an unparseable node"); + wrapper.get(key, proof, root); + } else if (listLen == 3) { + // Node with list of 3 + proof[4] = + hex"f79f204dcf44e265ba93879b2da89e1b16ab48fc5eb8e31bc16b0612d6da8463f195942536c09e5f5691498805884fa37811be3b2bddb480"; + // rehash all proof elements and insert it into the proof element above it + (proof[0], proof[1], proof[2], proof[3], root) = rehashOtherElements(proof[4]); + + vm.expectRevert("MerkleTrie: received an unparseable node"); + wrapper.get(key, proof, root); + } + } + + function rehashOtherElements(bytes memory _proof4) + private + pure + returns (bytes memory proof0_, bytes memory proof1_, bytes memory proof2_, bytes memory proof3_, bytes32 root_) + { + // rehash all proof elements and insert it into the proof element above it + proof3_ = bytes.concat( + hex"f8f1a069a092c7a950214e7e45b99012dc8ad112eab0fc94ae5ca9efbd6949068384f280a0b25c46db67ef7cf0c47bb400c31c85a26c5a204431527c964c8ecaf3d63e52cc80a0", + keccak256(_proof4), + hex"80808080a04a0ca9e3bed1bc3e3c819384d19b6d5e523164a6520c4eb42e828a63ef730ae38080a03b598ed1b9269d4b05e2e75cfb54298d25437669870c919a59a147d2d256fdba80a0db2d655057c83107a73d086cfdd8fcc74739bb48c652eb0ce597178ecf96b39aa05c66ac392a761341b9c22b773ea19af311f34ef537640b9bb96842ec6ace913280" + ); + proof2_ = bytes.concat( + hex"f90211a0065f58fbe63e8e3387e91047d5b7a4532e7d9de0abc47f04791aef27a140fdb5a0858beea29778551c01b0d3e542d707675856da9c3f1d065c845e55c24d77be89a0e90a410489eff6f4f8d70b0cce1fb1339117ec0f6f1db195a6cc410509a2ebaea078ba7fe504e8d01d57f6bee52c4938d779108e500b5923272441ed2964b8c45da0f0430ed9fa807e5fb6ace75f8766ea60009d8539e00006e359f5f7bc38a76596a0a98a7938db99a2d80abea6349de42bf2576c9e51cc715c85fbacab365ec16f5ba0", + keccak256(proof3_), + hex"a0ca48cad1e00d22d6146173341a6060378e738be727a7265a923cf6bfd1f8b610a0f8a4aae21a78ac28e2a61f50396f9a80f6c8232fe4afa203160361c0962242baa09a1029479959fb29b4da7239393fd6ca20bc376d860324f429a51b0e0565a158a0eefb84d3943d680e176258dffe0104ac48c171a8574a811535256a2d8ba531dea062a3d709a2f70ba1970842c4f20a602291273d1f6022e7a14cde2afdcd51e795a0397e6b9b87012cd79cbd0bb7daa4cc43830a673d80b65fb88c0449140175d89ca0f8a4c73c0078cbd32961227910e3f9315bc587716062e39f66be19747ccf9b67a0ea4bdd1b187fdba273a8625f88f284994d19c38ec58651839852665717d953d9a0319ebf356f45da83c7f106f1fd3decbf15f651fad3389a0d279602cdea8ee11480" + ); + proof1_ = bytes.concat( + hex"f90211a0db246208c4cef45e9aeb9f1df1baa8572675bc453f7da538165a2bb9e6a4c416a0d26d82a9ddff901d2a1f9e18506120dec0e5b3c95549c5bff0efc355061ea73fa04f1cedbb5c7df7ee5cc3210980baf5537affb29c661c6a4eeb193bc42e7fbc74a0acea389e0cf577d0e13483d98b15c82618ac18b7cc4a479981e3e672ddd16867a0ef59a06aeea1eb5ba1313bbe1fa74ff264d84d7319ab6178213734b5b5efa9c1a08f85dc6001713d77aa4e12982dfdb28fd1c7dcc290d46f2749e8a7d67ba2a694a0f6698ff794881edc50340b75311de64ce3da5f97debcfdfd4d20de57ef3ba7eba0680071ce05e9c7915f731bac8b9673332d1d77ea1f7dadab36d9b233eea32ba4a035ad3686f436232360c2aa364c9f2aa2081318b9fb33cd1050d69ee46f791d62a03b495b3d65d9ae39680a0f835c1d1378d218f7b1fb88d2b2c6ac6ef916f09172a0a808d1e8c632d9a6cfeb3c2c123a58b5b3e1998d4bd02c5fb0f7c5d4ba1338e6a0369376e9152831135ff3a902c9740cf22951d67edd51bf0541565e379d7efc25a0", + keccak256(proof2_), + hex"a0278081783022e748dc70874a72377038935c00c1f0a24bbb8cd0fc208d8b68f4a06c4e83593571b94d08cb78ece0de4920b02a650a47a16583f94c8fe35f724707a0cd7eb9d730e5138fd943200b577e7bbb827d010a50d19af2f4b19ef19658156d80" + ); + proof0_ = bytes.concat( + hex"f90211a085ed702d58e6a962ad0e785e5c9036e06d878fd065eb9669122447f6aee7957da05badb8cfd5a7493d928614730af6e14eabe2c93fbac93c853dde3270c446309da0", + keccak256(proof1_), + hex"a0fe3143892366faeb9fae1117b888263afe0f74e6c73555fee53a604bf7188431a0af2c79f0dddd15d6f62e3fa60d515c44d58444ad3915c7ca4bddb31c8f148d0ca08f37a2f9093a4aee39519f3a06fe4674cc670fbbbd7a5f4eb096310b7bc1fdc9a086bd12d2031d9714130c687e6822250fa24b3147824780bea96cf8a7406c8966a03e42538ba2da8adaa0eca4550ef62de4dabde8ca06b71ac1b276ff31b67a7655a04a439f7eb6a62c77ec921139925af3359f61d16e083076e0e425583289107d7da0c453a51991b5a4c6174ddff77c0b7d9cc86f05ffda6ff523e2365f19797c7a00a06f43b7b9a118264ab4b6c24d7d3de77f39071a298426bfc27180adfca57d590da0032e0db4dcf122d4bdb1d4ec3c5df5fabd3127bcefe412cb046b7f0d80d11c9fa0560c2b8c9466b8cb5ffd600f24ea0ed9838bfdab7870d505d4387c2468d3c498a0597996e939ff8c29c9e59dc47c111e760450a9c4fe2b065825762da2a1f32495a0e3411c9af104364230c49de5a4d0802c84df18beee9778673364e1747a875622a02a6928825356d8280f361a02285af30e73889f4e55ecb63ed85c8581e07061d680" + ); + root_ = keccak256(proof0_); + } +} + +contract MerkleTrieWrapper { + function get(bytes memory key, bytes[] memory proof, bytes32 root) external pure returns (bytes memory) { + return MerkleTrie.get(key, proof, root); + } } From 16a5d617f3ab360e0b58b7ebe97a9956b576fa4b Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Wed, 27 Nov 2024 18:38:59 -0500 Subject: [PATCH 58/61] maint: clean up primary justfile (#12997) Various things in the primary justfile weren't particularly legible, particularly around installing tooling versions. Cleans up the primary justfile so that everything has comments and the process for installing tooling is unified. Co-authored-by: Matthew Slipper --- justfile | 81 +++++++++++++++++++++++++--------- ops/scripts/install-foundry.sh | 6 +++ ops/scripts/install-kontrol.sh | 17 +++++++ 3 files changed, 83 insertions(+), 21 deletions(-) create mode 100755 ops/scripts/install-kontrol.sh diff --git a/justfile b/justfile index 6438ba36197..acf6d8bc602 100644 --- a/justfile +++ b/justfile @@ -1,4 +1,5 @@ -issues: +# Checks that TODO comments have corresponding issues. +todo-checker: ./ops/scripts/todo-checker.sh # Runs semgrep on the entire monorepo. @@ -9,56 +10,94 @@ semgrep: semgrep-test: semgrep scan --test --config .semgrep/rules/ .semgrep/tests/ -lint-shellcheck: +# Runs shellcheck. +shellcheck: find . -type f -name '*.sh' -not -path '*/node_modules/*' -not -path './packages/contracts-bedrock/lib/*' -not -path './packages/contracts-bedrock/kout*/*' -exec sh -c 'echo "Checking $1"; shellcheck "$1"' _ {} \; +######################################################## +# DEPENDENCY MANAGEMENT # +######################################################## + +# Generic task for checking if a tool version is up to date. +check-tool-version tool: + #!/usr/bin/env bash + EXPECTED=$(jq -r .{{tool}} < versions.json) + ACTUAL=$(just print-{{tool}}) + if [ "$ACTUAL" = "$EXPECTED" ]; then + echo "✓ {{tool}} versions match" + else + echo "✗ {{tool}} version mismatch (expected $EXPECTED, got $ACTUAL), run 'just install-{{tool}}' to upgrade" + exit 1 + fi + +# Installs foundry install-foundry: - curl -L https://foundry.paradigm.xyz | bash && just update-foundry - -update-foundry: bash ./ops/scripts/install-foundry.sh +# Prints current foundry version. +print-foundry: + forge --version + +# Checks if installed foundry version is correct. check-foundry: bash ./ops/scripts/check-foundry.sh +# Installs correct kontrol version. install-kontrol: - curl -L https://kframework.org/install | bash && just update-kontrol + bash ./ops/scripts/install-kontrol.sh + +# Prints current kontrol version. +print-kontrol: + kontrol version -update-kontrol: - kup install kontrol --version v$(jq -r .kontrol < versions.json) +# Checks if installed kontrol version is correct. +check-kontrol: + just check-tool-version kontrol +# Installs correct abigen version. install-abigen: go install github.com/ethereum/go-ethereum/cmd/abigen@$(jq -r .abigen < versions.json) +# Prints current abigen version. print-abigen: abigen --version | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' -e 's/ /./g' -e 's/^/v/' +# Checks if installed abigen version is correct. check-abigen: - [[ $(just print-abigen) = $(cat versions.json | jq -r '.abigen') ]] && echo '✓ abigen versions match' || (echo '✗ abigen version mismatch. Run `just upgrade:abigen` to upgrade.' && exit 1) - -upgrade-abigen: - jq '.abigen = $v' --arg v $(just print:abigen) <<<$(cat versions.json) > versions.json + just check-tool-version abigen +# Installs correct slither version. install-slither: pip3 install slither-analyzer==$(jq -r .slither < versions.json) +# Prints current slither version. print-slither: slither --version +# Checks if installed slither version is correct. check-slither: - [[ $(just print-slither) = $(jq -r .slither < versions.json) ]] && echo '✓ slither versions match' || (echo '✗ slither version mismatch. Run `just upgrade-slither` to upgrade.' && exit 1) - -upgrade-slither: - jq '.slither = $v' --arg v $(just print-slither) <<<$(cat versions.json) > versions.json + just check-tool-version slither +# Installs correct semgrep version. install-semgrep: - pip3 install semgrep + pip3 install semgrep=="$(jq -r .semgrep < versions.json)" +# Prints current semgrep version. print-semgrep: - semgrep --version + semgrep --version | head -n 1 +# Checks if installed semgrep version is correct. check-semgrep: - [ "$(just print-semgrep)" = "$(jq -r .semgrep < versions.json)" ] && echo '✓ semgrep versions match' || (echo '✗ semgrep version mismatch. Run `just upgrade-semgrep` to upgrade.' && exit 1) + just check-tool-version semgrep -upgrade-semgrep: - pip3 install semgrep=="$(jq -r .semgrep < versions.json)" +# Installs correct go version. +install-go: + echo "error: go must be installed manually" && exit 1 + +# Prints current go version. +print-go: + go version | sed -E 's/.*go([0-9]+\.[0-9]+\.[0-9]+).*/\1/' + +# Checks if installed go version is correct. +check-go: + just check-tool-version go diff --git a/ops/scripts/install-foundry.sh b/ops/scripts/install-foundry.sh index 654ed6b87f7..f8ed7924bf8 100755 --- a/ops/scripts/install-foundry.sh +++ b/ops/scripts/install-foundry.sh @@ -2,6 +2,12 @@ set -e +# Check if foundryup exists, if not, install it +if ! command -v foundryup &> /dev/null; then + echo "foundryup not found, installing..." + curl -L https://foundry.paradigm.xyz | bash +fi + SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) MONOREPO_DIR=$(cd "$SCRIPTS_DIR/../../" && pwd) diff --git a/ops/scripts/install-kontrol.sh b/ops/scripts/install-kontrol.sh new file mode 100755 index 00000000000..5d4044d26b2 --- /dev/null +++ b/ops/scripts/install-kontrol.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +# Check if kup exists, if not, install it +if ! command -v kup &> /dev/null; then + echo "kup not found, installing..." + yes | bash <(curl -L https://kframework.org/install) +fi + +SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +MONOREPO_DIR=$(cd "$SCRIPTS_DIR/../../" && pwd) + +# Grab the correct kontrol version. +VERSION=$(jq -r .kontrol < "$MONOREPO_DIR"/versions.json) + +kup install kontrol --version v"$VERSION" From e84868c27776fd04dc77e95176d55c8f6b1cc9a3 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Thu, 28 Nov 2024 14:31:15 +0100 Subject: [PATCH 59/61] update lib keccak dependency (#13136) * update lib keccak dependency * update semver-lock * update semver-lock --- packages/contracts-bedrock/lib/lib-keccak | 2 +- packages/contracts-bedrock/snapshots/semver-lock.json | 4 ++-- packages/contracts-bedrock/src/cannon/PreimageOracle.sol | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/lib/lib-keccak b/packages/contracts-bedrock/lib/lib-keccak index 0115edbbc60..3b1e7bbb4cc 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/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 35696bc7bf1..8bd5ea33f77 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -148,8 +148,8 @@ "sourceCodeHash": "0x7ddcf8584f9bd92abd1eb45bc198f5b0ec54acaf292f60e919d674cc56fb8abc" }, "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/PreimageOracle.sol b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol index 7ac7c33d99d..03c0b3ae552 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 // From 26f7a40fc11347bafab5dfb4a2b81bdd36fcb456 Mon Sep 17 00:00:00 2001 From: George Knee Date: Thu, 28 Nov 2024 18:19:24 +0000 Subject: [PATCH 60/61] txmgr: `Queue.Send()` uses `q.txMgr.SendAsync` (#13120) * txmgr: Queue.Send() uses q.txMgr.SendAsync This should ensure that transactions are confirmed on chain in the order Queue.Send() is called, without sacrificing parallel tx submission. * implement SendAsync in op-challenger test stubTxMgr It doesn't preserve the nonces like the production txMgr does. * TrySend also ensures synchronous tx nonce ordering (on success) * factor out HandleResponse fn * remove unused code * unexport handler --- op-challenger/sender/sender_test.go | 8 ++++- op-service/txmgr/queue.go | 49 +++++++++++++++++++---------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/op-challenger/sender/sender_test.go b/op-challenger/sender/sender_test.go index 5169ae67192..1d4e17047b7 100644 --- a/op-challenger/sender/sender_test.go +++ b/op-challenger/sender/sender_test.go @@ -129,8 +129,14 @@ func (s *stubTxMgr) Send(ctx context.Context, candidate txmgr.TxCandidate) (*typ return <-ch, nil } +// SendAsync simply wraps Send to make it non blocking. It does not guarantee transaction nonce ordering, +// unlike the production txMgr. func (s *stubTxMgr) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { - panic("unimplemented") + go func() { + receipt, err := s.Send(ctx, candidate) + resp := txmgr.SendResponse{Receipt: receipt, Err: err} + ch <- resp + }() } func (s *stubTxMgr) recordTx(candidate txmgr.TxCandidate) chan *types.Receipt { diff --git a/op-service/txmgr/queue.go b/op-service/txmgr/queue.go index ee7a03ffa92..c48687d459e 100644 --- a/op-service/txmgr/queue.go +++ b/op-service/txmgr/queue.go @@ -51,17 +51,36 @@ func (q *Queue[T]) Wait() error { return q.group.Wait() } +// handleResponse will wait for the response on the first passed channel, +// and then forward it on the second passed channel (attaching the id). It returns +// the response error or the context error if the context is canceled. +func handleResponse[T any](ctx context.Context, c chan SendResponse, d chan TxReceipt[T], id T) error { + select { + case response := <-c: + d <- TxReceipt[T]{ID: id, Receipt: response.Receipt, Err: response.Err} + return response.Err + case <-ctx.Done(): + d <- TxReceipt[T]{ID: id, Err: ctx.Err()} + return ctx.Err() + } +} + // Send will wait until the number of pending txs is below the max pending, -// and then send the next tx. +// and then send the next tx asynchronously. The nonce of the transaction is +// determined synchronously, so transactions should be confirmed on chain in +// the order they are sent using this method. // // The actual tx sending is non-blocking, with the receipt returned on the // provided receipt channel. If the channel is unbuffered, the goroutine is // blocked from completing until the channel is read from. func (q *Queue[T]) Send(id T, candidate TxCandidate, receiptCh chan TxReceipt[T]) { group, ctx := q.groupContext() - group.Go(func() error { - return q.sendTx(ctx, id, candidate, receiptCh) - }) + responseChan := make(chan SendResponse, 1) + handleResponse := func() error { + return handleResponse(ctx, responseChan, receiptCh, id) + } + group.Go(handleResponse) // This blocks until the number of handlers is below the limit + q.txMgr.SendAsync(ctx, candidate, responseChan) // Nonce management handled synchronously, i.e. before this returns } // TrySend sends the next tx, but only if the number of pending txs is below the @@ -75,19 +94,17 @@ func (q *Queue[T]) Send(id T, candidate TxCandidate, receiptCh chan TxReceipt[T] // blocked from completing until the channel is read from. func (q *Queue[T]) TrySend(id T, candidate TxCandidate, receiptCh chan TxReceipt[T]) bool { group, ctx := q.groupContext() - return group.TryGo(func() error { - return q.sendTx(ctx, id, candidate, receiptCh) - }) -} - -func (q *Queue[T]) sendTx(ctx context.Context, id T, candidate TxCandidate, receiptCh chan TxReceipt[T]) error { - receipt, err := q.txMgr.Send(ctx, candidate) - receiptCh <- TxReceipt[T]{ - ID: id, - Receipt: receipt, - Err: err, + responseChan := make(chan SendResponse, 1) + handleResponse := func() error { + return handleResponse(ctx, responseChan, receiptCh, id) + } + ok := group.TryGo(handleResponse) + if !ok { + return false + } else { + q.txMgr.SendAsync(ctx, candidate, responseChan) + return true } - return err } // groupContext returns a Group and a Context to use when sending a tx. From 4a45ed2f905bd56d5e31fdf4e5188ac3a25a2619 Mon Sep 17 00:00:00 2001 From: agusduha Date: Thu, 28 Nov 2024 17:47:20 -0300 Subject: [PATCH 61/61] fix: pre pr --- .../contracts-bedrock/snapshots/semver-lock.json | 14 +++++++------- .../src/L1/OptimismPortalInterop.sol | 4 ++-- .../contracts-bedrock/src/L1/SuperchainConfig.sol | 4 ++-- .../src/L1/SystemConfigInterop.sol | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 0e793dcf823..889a15db750 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -32,8 +32,8 @@ "sourceCodeHash": "0xb7cbcb27240d0fd85a7a3009676abb93679e3b8723a967c1f310390464399869" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x831af803158768b7fc229822eebda0ce7922cb1852fd770856b425023a379d47", - "sourceCodeHash": "0xe1dbe5e95ffed6587126ea65a5e4d3c8f11e1bd17a194a5665c7f0c0d32f29e3" + "initCodeHash": "0xbcd9d2a47e2b6076d242762cc072387d9da5532b72d9f0286de2d683cd918b13", + "sourceCodeHash": "0xd3f70c69c35d05f0eec20ac7dae4d86b20066af2b2395387cc62ad80b5a27b06" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x98dc9a7ecd1919a8cf4bcca4fb28b112641b2aa5132fb5467a349fb80974957a", @@ -44,16 +44,16 @@ "sourceCodeHash": "0x26b7450f991fe197a94861cf618df04feb695dbbba884ffe93f96defa63e5bd7" }, "src/L1/SuperchainConfig.sol": { - "initCodeHash": "0x5cd6b119f03beea59e2ba29ea92694e6e5cbcbb1a83a02557ffbe332ce687ab6", - "sourceCodeHash": "0x1e191c7746b936427b8391c68a42b542eab0821c005a4a6a517bbe855278cced" + "initCodeHash": "0x56780fdb911f250dde8a5cfb2aae158405503cf295efd784ba9823667838bd99", + "sourceCodeHash": "0x3693d009d1d02508adec63bcb6bf2e7a6ec5f8255ddff8ffdcb792fae0cd4b84" }, "src/L1/SystemConfig.sol": { "initCodeHash": "0x0eda38e2fb2687a324289f04ec8ad0d2afe51f45219d074740fb4a0e24ea6569", "sourceCodeHash": "0x6dbbe8716ca8cd2fba3da8dcae0ca0c4b1f3e9dd04220fb24a15666b23300927" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x9376acb45613d5042ac316f3dd0fa09e7ea1f7b9e99a879b81a8cc31185ed3c7", - "sourceCodeHash": "0x40d76b65fa9074a6539de9a73f0735badb1fc1fe0a0b1b42829065ba6376b176" + "initCodeHash": "0x1d122143f63b5c00af41a246b1099ee968af04df7af394db874613d80bc20898", + "sourceCodeHash": "0x2e928783bce90409817c223e6746b74f4c164d614bcf0b0f26a1b82811882974" }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0xc23d0437deb5c2e9f8831b9325c77e9d07467c9286f81c0ef47cfef4e242f96b", @@ -227,4 +227,4 @@ "initCodeHash": "0x06ae2c0b39c215b7fa450d382916ce6f5c6f9f2d630e572db6b72d688255b3fd", "sourceCodeHash": "0xa014d9c992f439dee8221e065828c3326ca2c4f5db0e83431c64c20f7e51ec14" } -} +} \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 2e065049fa3..c22776ef3a1 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -26,9 +26,9 @@ contract OptimismPortalInterop is OptimismPortal2 { OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds, _sharedLockbox) { } - /// @custom:semver +interop-beta.3 + /// @custom:semver +interop-beta.4 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.3"); + return string.concat(super.version(), "+interop-beta.4"); } /// @notice Sets static configuration options for the L2 system. diff --git a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol index ede2daf9919..369b48a3398 100644 --- a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol +++ b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol @@ -62,8 +62,8 @@ contract SuperchainConfig is Initializable, ISemver { error ChainAlreadyAdded(); /// @notice Semantic version. - /// @custom:semver 1.1.1-beta.2 - string public constant version = "1.1.1-beta.2"; + /// @custom:semver 1.1.1-beta.3 + string public constant version = "1.1.1-beta.3"; // Mapping from chainId to SystemConfig address mapping(uint256 => address) public systemConfigs; diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol index 48efa6bca53..c215404bd11 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol @@ -29,9 +29,9 @@ contract SystemConfigInterop is SystemConfig { /// @notice The address of the SuperchainConfig contract. address public immutable SUPERCHAIN_CONFIG; - /// @custom:semver +interop-beta.5 + /// @custom:semver +interop-beta.6 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.5"); + return string.concat(super.version(), "+interop-beta.6"); } /// @notice Constructs the SystemConfig contract.