diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/.env b/mainnet/2024-03-07-ecotome-sysconfig-updates/.env new file mode 100644 index 00000000..e69de29b diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/Makefile b/mainnet/2024-03-07-ecotome-sysconfig-updates/Makefile new file mode 100644 index 00000000..aff5bb0c --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/Makefile @@ -0,0 +1,55 @@ +include ../../Makefile +include ../.env +include .env + +ifndef LEDGER_ACCOUNT +override LEDGER_ACCOUNT = 0 +endif + +## +# Incident response commands +# Note that --ledger --hd-paths can be replaced with --private-key $(PRIVATE_KEY) +# in any command when using a local key. +## + +# Delete L2 Outputs Commands + +.PHONY: delete-outputs-sign +delete-outputs-sign: deps + $(GOPATH)/bin/eip712sign --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" -- \ + forge script --rpc-url $(L1_RPC_URL) DeleteL2Outputs --sig "sign()" + +.PHONY: delete-outputs-run +delete-outputs-run: deps + forge script --rpc-url $(L1_RPC_URL) \ + DeleteL2Outputs --sig "run(bytes)" $(SIGNATURES) \ + --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" \ + --broadcast + +# Pause OptimismPortal Commands + +.PHONY: pause-portal-sign +pause-portal-sign: deps + $(GOPATH)/bin/eip712sign --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" -- \ + forge script --rpc-url $(L1_RPC_URL) PausePortal --sig "sign()" + +.PHONY: pause-portal-run +pause-portal-run: deps + forge script --rpc-url $(L1_RPC_URL) \ + PausePortal --sig "run(bytes)" $(SIGNATURES) \ + --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" \ + --broadcast + +# Unpause OptimismPortal Commands + +.PHONY: unpause-portal-sign +unpause-portal-sign: deps + $(GOPATH)/bin/eip712sign --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" -- \ + forge script --rpc-url $(L1_RPC_URL) UnpausePortal --sig "sign()" + +.PHONY: unpause-portal-run +unpause-portal-run: deps + forge script --rpc-url $(L1_RPC_URL) \ + UnpausePortal --sig "run(bytes)" $(SIGNATURES) \ + --ledger --hd-paths "m/44'/60'/$(LEDGER_ACCOUNT)'/0/0" \ + --broadcast \ No newline at end of file diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/foundry.toml b/mainnet/2024-03-07-ecotome-sysconfig-updates/foundry.toml new file mode 100644 index 00000000..0be0575a --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/foundry.toml @@ -0,0 +1,20 @@ +[profile.default] +src = 'src' +out = 'out' +libs = ['lib'] +broadcast = 'records' +fs_permissions = [ {access = "read-write", path = "./"} ] +optimizer = true +optimizer_runs = 999999 +solc_version = "0.8.15" +via-ir = true +remappings = [ + '@eth-optimism-bedrock/=lib/optimism/packages/contracts-bedrock/', + '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts', + '@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts', + '@rari-capital/solmate/=lib/solmate/', + '@base-contracts/=lib/base-contracts', + 'solady/=lib/solady/src/' +] + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/DeleteL2Outputs.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/DeleteL2Outputs.s.sol new file mode 100644 index 00000000..07d034f3 --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/DeleteL2Outputs.s.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@eth-optimism-bedrock/contracts/L1/L2OutputOracle.sol"; +import "@base-contracts/src/Challenger1of2.sol"; +import "@base-contracts/script/universal/MultisigBuilder.sol"; + +contract DeleteL2Outputs is MultisigBuilder { + address constant internal L2_OUTPUT_ORACLE_PROXY = vm.envAddress("L2_OUTPUT_ORACLE_PROXY"); // TODO: define L2_OUTPUT_ORACLE_PROXY=xxx in the .env file + address constant internal CHALLENGER = vm.envAddress("CHALLENGER"); // TODO: define CHALLENGER=xxx in the .env file + address constant internal SAFE = vm.envAddress("SAFE"); // TODO: define SAFE=xxx in the .env file - ie the multisig which is signer on challenger> + uint256 constant internal L2_OUTPUT_INDEX = vm.envAddress("L2_OUTPUT_INDEX"); // TODO: define L2_OUTPUT_INDEX=xxx in the .env file - this is the index start deleting from (everything after will be deleted) + + function _postCheck() internal override view { + L2OutputOracle l2OutputOracle = L2OutputOracle(L2_OUTPUT_ORACLE_PROXY); + require(l2OutputOracle.latestOutputIndex() < L2_OUTPUT_INDEX, "DeleteL2Outputs: L2OutputOracle did not get deleted"); + } + + function _buildCalls() internal override view returns (IMulticall3.Call3[] memory) { + IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1); + + L2OutputOracle l2OutputOracle = L2OutputOracle(L2_OUTPUT_ORACLE_PROXY); + bytes memory deleteL2OutputData = abi.encodeCall( + L2OutputOracle.deleteL2Outputs, (L2_OUTPUT_INDEX) + ); + + calls[0] = IMulticall3.Call3({ + target: CHALLENGER, + allowFailure: false, + callData: abi.encodeCall( + Challenger1of2.execute, (deleteL2OutputData) + ) + }); + + return calls; + } + + function _ownerSafe() internal override view returns (address) { + return SAFE; + } +} diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/PausePortal.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/PausePortal.s.sol new file mode 100644 index 00000000..cba5e253 --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/PausePortal.s.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@base-contracts/script/universal/MultisigBuilder.sol"; +import "@eth-optimism-bedrock/contracts/L1/OptimismPortal.sol"; + +contract PausePortal is MultisigBuilder { + address constant internal OPTIMISM_PORTAL_PROXY = vm.envAddress("OPTIMISM_PORTAL_PROXY"); // TODO: define OPTIMISM_PORTAL_PROXY=xxx in the .env file + address constant internal GUARDIAN = vm.envAddress("GUARDIAN"); // TODO: define GUARDIAN=xxx in the .env file + + function _postCheck() internal override view { + OptimismPortal optimismPortal = OptimismPortal(payable(OPTIMISM_PORTAL_PROXY)); + require(optimismPortal.paused() == true, "PausePortal: Portal did not get paused"); + } + + function _buildCalls() internal override view returns (IMulticall3.Call3[] memory) { + IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1); + + calls[0] = IMulticall3.Call3({ + target: OPTIMISM_PORTAL_PROXY, + allowFailure: false, + callData: abi.encodeCall( + OptimismPortal.pause, () + ) + }); + + return calls; + } + + function _ownerSafe() internal override view returns (address) { + return GUARDIAN; + } +} diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetBatcher.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetBatcher.s.sol new file mode 100644 index 00000000..c8ec7900 --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetBatcher.s.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@eth-optimism-bedrock/src/L1/SystemConfig.sol"; +import "@base-contracts/script/universal/MultisigBuilder.sol"; + +contract SetBatcherAddr is MultisigBuilder { + address constant internal NEW_BATCHER = vm.envAddress("NEW_BATCHER_ADDR"); // TODO: define NEW_BATCHER_ADDR=xxx in the .env file + address constant internal SYSTEM_CONFIG = vm.envAddress("SYSTEM_CONFIG_ADDR"); // TODO: define SYSTEM_CONFIG_ADDR=xxx in the .env file + address internal SYSTEM_CONFIG_OWNER = vm.envAddress("SYSTEM_CONFIG_OWNER"); // TODO: define SYSTEM_CONFIG_OWNER=xxx in the .env file + + + function _postCheck() internal override view { + SystemConfig systemConfig = SystemConfig(SYSTEM_CONFIG); + bytes32 batcherHash = bytes32(abi.encode(NEW_BATCHER)); + require(systemConfig.batcherHash() == batcherHash, "SetBatcherAddr: batcherHash not set correctly"); + } + + function _buildCalls() internal override view returns (IMulticall3.Call3[] memory) { + IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1); + + bytes32 batcherHash = bytes32(abi.encode(NEW_BATCHER)); + + calls[0] = IMulticall3.Call3({ + target: SYSTEM_CONFIG, + allowFailure: false, + callData: abi.encodeCall( + SystemConfig.setBatcherHash, + (batcherHash) + ) + }); + + return calls; + } + + function _ownerSafe() internal override view returns (address) { + return SYSTEM_CONFIG_OWNER; + } +} \ No newline at end of file diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetupNewProposer.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetupNewProposer.s.sol new file mode 100644 index 00000000..7903b2ed --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/SetupNewProposer.s.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@eth-optimism-bedrock/contracts/L1/L2OutputOracle.sol"; +import "forge-std/Script.sol"; + +contract SetupNewProposer is Script { + address constant internal NEW_PROPOSER = vm.envUint("NEW_PROPOSER"); // TODO: define NEW_PROPOSER=xxx in the .env file + address constant internal DEPLOYER = vm.envAddress("DEPLOYER"); // TODO: define DEPLOYER=xxx in the .env file + address constant internal L2_OUTPUT_ORACLE_PROXY = vm.envAddress("L2_OUTPUT_ORACLE_PROXY"); // TODO: define L2_OUTPUT_ORACLE_PROXY=xxx in the .env file + + function run() public { + L2OutputOracle existingL2OO = L2OutputOracle(L2_OUTPUT_ORACLE_PROXY); + uint256 oldSubmissionInterval = existingL2OO.SUBMISSION_INTERVAL(); + uint256 oldL2BlockTime = existingL2OO.L2_BLOCK_TIME(); + uint256 oldFinalizationPeriodSeconds = existingL2OO.FINALIZATION_PERIOD_SECONDS(); + uint256 startingBlockNumber = existingL2OO.startingBlockNumber(); + uint256 startingTimestamp = existingL2OO.startingTimestamp(); + address oldProposer = existingL2OO.PROPOSER(); + address oldChallenger = existingL2OO.CHALLENGER(); + + console.log(oldProposer); + console.log(NEW_PROPOSER); + + // Deploy L2OutputOracle new implementation wiht the new submission interval + vm.broadcast(DEPLOYER); + L2OutputOracle l2OutputOracleImpl = new L2OutputOracle({ + _submissionInterval: oldSubmissionInterval, + _l2BlockTime: oldL2BlockTime, + _startingBlockNumber: startingBlockNumber, + _startingTimestamp: startingTimestamp, + _proposer: NEW_PROPOSER, + _challenger: oldChallenger, + _finalizationPeriodSeconds: oldFinalizationPeriodSeconds + }); + + require(l2OutputOracleImpl.L2_BLOCK_TIME() == oldL2BlockTime, "Deploy: l2OutputOracle l2BlockTime is incorrect"); + require(l2OutputOracleImpl.PROPOSER() == NEW_PROPOSER, "Deploy: l2OutputOracle proposer is incorrect"); + + console.logAddress(address(l2OutputOracleImpl)); + } +} \ No newline at end of file diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UnpausePortal.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UnpausePortal.s.sol new file mode 100644 index 00000000..0516fe30 --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UnpausePortal.s.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@base-contracts/script/universal/MultisigBuilder.sol"; +import "@eth-optimism-bedrock/contracts/L1/OptimismPortal.sol"; + +contract UnpausePortal is MultisigBuilder { + address constant internal OPTIMISM_PORTAL_PROXY = vm.envAddress("OPTIMISM_PORTAL_PROXY"); // TODO: define OPTIMISM_PORTAL_PROXY=xxx in the .env file + address constant internal GUARDIAN = vm.envAddress("GUARDIAN"); // TODO: define GUARDIAN=xxx in the .env file + + function _postCheck() internal override view { + OptimismPortal optimismPortal = OptimismPortal(payable(OPTIMISM_PORTAL_PROXY)); + require(optimismPortal.paused() == false, "UnpausePortal: Portal did not get unpaused"); + } + + function _buildCalls() internal override view returns (IMulticall3.Call3[] memory) { + IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1); + + calls[0] = IMulticall3.Call3({ + target: OPTIMISM_PORTAL_PROXY, + allowFailure: false, + callData: abi.encodeCall( + OptimismPortal.unpause, () + ) + }); + + return calls; + } + + function _ownerSafe() internal override view returns (address) { + return GUARDIAN; + } +} diff --git a/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UpdateProposer.s.sol b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UpdateProposer.s.sol new file mode 100644 index 00000000..53aa4ad5 --- /dev/null +++ b/mainnet/2024-03-07-ecotome-sysconfig-updates/script/UpdateProposer.s.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import "@eth-optimism-bedrock/src/universal/ProxyAdmin.sol"; +import "@base-contracts/script/universal/NestedMultisigBuilder.sol"; + +contract UpdateProposer is NestedMultisigBuilder { + // TODO: this assumes a new L2OutputOracle implementation contract has already been deployed. See SetupNewProposer.s.sol. + + address internal PROXY_ADMIN_CONTRACT = vm.envAddress("L1_PROXY_ADMIN"); // TODO: define L1_PROXY_ADMIN=xxx in the .env file + address internal PROXY_ADMIN_OWNER = vm.envAddress("L1_NESTED_SAFE"); // TODO: define L1_NESTED_SAFE=xxx in the .env file + address internal L2_OUTPUT_PROPOSER = vm.envAddress("L2_OUTPUT_PROPOSER"); // TODO: define L2_OUTPUT_PROPOSER=xxx in the .env file + address internal L2_OUTPUT_PROPOSER_NEW_IMPL = vm.envAddress("L2_OUTPUT_PROPOSER_NEW_IMPL"); // TODO: define L2_OUTPUT_PROPOSER_NEW_IMPL=xxx in the .env file + + function _postCheck() internal override view { + ProxyAdmin proxyAdmin = ProxyAdmin(PROXY_ADMIN_CONTRACT); + require(proxyAdmin.getProxyImplementation(L2_OUTPUT_PROPOSER).codehash == L2_OUTPUT_PROPOSER_NEW_IMPL.codehash); + } + + function _buildCalls() internal override view returns (IMulticall3.Call3[] memory) { + IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1); + + calls[0] = IMulticall3.Call3({ + target: PROXY_ADMIN_CONTRACT, + allowFailure: false, + callData: abi.encodeCall( + ProxyAdmin.upgrade, + (payable(L2_OUTPUT_PROPOSER), L2_OUTPUT_PROPOSER_NEW_IMPL) + ) + }); + + return calls; + } + + function _ownerSafe() internal override view returns (address) { + return PROXY_ADMIN_OWNER; + } +} \ No newline at end of file diff --git a/mainnet/2024-03-07-sysconfig-updates/.github/workflows/test.yml b/mainnet/2024-03-07-sysconfig-updates/.github/workflows/test.yml deleted file mode 100644 index 9282e829..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/.github/workflows/test.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: test - -on: workflow_dispatch - -env: - FOUNDRY_PROFILE: ci - -jobs: - check: - strategy: - fail-fast: true - - name: Foundry project - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Run Forge build - run: | - forge --version - forge build --sizes - id: build - - - name: Run Forge tests - run: | - forge test -vvv - id: test diff --git a/mainnet/2024-03-07-sysconfig-updates/.gitignore b/mainnet/2024-03-07-sysconfig-updates/.gitignore deleted file mode 100644 index 85198aaa..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Compiler files -cache/ -out/ - -# Ignores development broadcast logs -!/broadcast -/broadcast/*/31337/ -/broadcast/**/dry-run/ - -# Docs -docs/ - -# Dotenv file -.env diff --git a/mainnet/2024-03-07-sysconfig-updates/README.md b/mainnet/2024-03-07-sysconfig-updates/README.md deleted file mode 100644 index 9265b455..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/README.md +++ /dev/null @@ -1,66 +0,0 @@ -## Foundry - -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** - -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ - -## Usage - -### Build - -```shell -$ forge build -``` - -### Test - -```shell -$ forge test -``` - -### Format - -```shell -$ forge fmt -``` - -### Gas Snapshots - -```shell -$ forge snapshot -``` - -### Anvil - -```shell -$ anvil -``` - -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` diff --git a/mainnet/2024-03-07-sysconfig-updates/foundry.toml b/mainnet/2024-03-07-sysconfig-updates/foundry.toml deleted file mode 100644 index 25b918f9..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/foundry.toml +++ /dev/null @@ -1,6 +0,0 @@ -[profile.default] -src = "src" -out = "out" -libs = ["lib"] - -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/mainnet/2024-03-07-sysconfig-updates/script/Counter.s.sol b/mainnet/2024-03-07-sysconfig-updates/script/Counter.s.sol deleted file mode 100644 index df9ee8b0..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/script/Counter.s.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; - -contract CounterScript is Script { - function setUp() public {} - - function run() public { - vm.broadcast(); - } -} diff --git a/mainnet/2024-03-07-sysconfig-updates/src/Counter.sol b/mainnet/2024-03-07-sysconfig-updates/src/Counter.sol deleted file mode 100644 index aded7997..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/src/Counter.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } - - function increment() public { - number++; - } -} diff --git a/mainnet/2024-03-07-sysconfig-updates/test/Counter.t.sol b/mainnet/2024-03-07-sysconfig-updates/test/Counter.t.sol deleted file mode 100644 index 54b724f7..00000000 --- a/mainnet/2024-03-07-sysconfig-updates/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } -}