From 60b57c9740d827c9c7b3b748fc142bc47e3e7c32 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Date: Tue, 8 Oct 2024 17:07:11 -0400 Subject: [PATCH] feat: Add deploy script (SC-713) (#28) * feat: deploy lib working * feat: start script * forge install: spark-address-registry * feat: add initial script * fix: rm guardian * feat: working deploy * feat: demonstrate issue * feat: fix test * fix: use sender flag * feat: fix script * feat: add logs --- .gitmodules | 3 ++ Makefile | 2 ++ deploy/Deploy.sol | 33 +++++++++++++++++++ lib/spark-address-registry | 1 + script/Deploy.s.sol | 30 +++++++++++++++++ test/ArbitrumOneCrosschainTest.t.sol | 2 +- test/CrosschainTestBase.sol | 8 ++--- test/Deploy.t.sol | 48 ++++++++++++++++++++++++++++ 8 files changed, 122 insertions(+), 5 deletions(-) create mode 100644 Makefile create mode 100644 deploy/Deploy.sol create mode 160000 lib/spark-address-registry create mode 100644 script/Deploy.s.sol create mode 100644 test/Deploy.t.sol diff --git a/.gitmodules b/.gitmodules index 971eeea..b81ad6e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "lib/spark-address-registry"] + path = lib/spark-address-registry + url = https://github.com/marsfoundation/spark-address-registry diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5157e11 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +deploy-base :; forge script script/Deploy.s.sol:DeployBaseExecutor --sender ${ETH_FROM} --broadcast --verify + diff --git a/deploy/Deploy.sol b/deploy/Deploy.sol new file mode 100644 index 0000000..580207d --- /dev/null +++ b/deploy/Deploy.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import { OptimismReceiver } from 'lib/xchain-helpers/src/receivers/OptimismReceiver.sol'; + +import { Executor } from 'src/Executor.sol'; + +library Deploy { + + function deployExecutor(uint256 delay, uint256 gracePeriod) + internal returns (address executor) + { + executor = address(new Executor(delay, gracePeriod)); + } + + function deployOptimismReceiver(address l1Authority, address executor) + internal returns (address receiver) + { + receiver = address(new OptimismReceiver(l1Authority, executor)); + } + + function setUpExecutorPermissions(address executor_, address receiver, address deployer) + internal + { + // NOTE: Using implementation instead of interface because OZ didn't define + // DEFAULT_ADMIN_ROLE in the IAccessControl interface. + Executor executor = Executor(executor_); + + executor.grantRole(executor.SUBMISSION_ROLE(), receiver); + executor.revokeRole(executor.DEFAULT_ADMIN_ROLE(), deployer); + } + +} diff --git a/lib/spark-address-registry b/lib/spark-address-registry new file mode 160000 index 0000000..121e0fc --- /dev/null +++ b/lib/spark-address-registry @@ -0,0 +1 @@ +Subproject commit 121e0fcd77732075aaa81065d24f79a519794fa4 diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol new file mode 100644 index 0000000..78806f9 --- /dev/null +++ b/script/Deploy.s.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import { console } from "forge-std/console.sol"; + +import { Ethereum } from "lib/spark-address-registry/src/Ethereum.sol"; + +import { Script } from 'forge-std/Script.sol'; + +import { Deploy } from "../deploy/Deploy.sol"; + +contract DeployBaseExecutor is Script { + + function run() public { + vm.createSelectFork(getChain("base").rpcUrl); + + vm.startBroadcast(); + + address executor = Deploy.deployExecutor(100, 1000); + address receiver = Deploy.deployOptimismReceiver(Ethereum.SPARK_PROXY, executor); + + console.log("executor deployed at:", executor); + console.log("receiver deployed at:", receiver); + + Deploy.setUpExecutorPermissions(executor, receiver, msg.sender); + + vm.stopBroadcast(); + } + +} diff --git a/test/ArbitrumOneCrosschainTest.t.sol b/test/ArbitrumOneCrosschainTest.t.sol index 2a88bf8..284e774 100644 --- a/test/ArbitrumOneCrosschainTest.t.sol +++ b/test/ArbitrumOneCrosschainTest.t.sol @@ -34,7 +34,7 @@ contract ArbitrumOneCrosschainTest is CrosschainTestBase { )); mainnet.selectFork(); - vm.deal(L1_EXECUTOR, 0.01 ether); + vm.deal(L1_SPARK_PROXY, 0.01 ether); } function relayMessagesAcrossBridge() internal override { diff --git a/test/CrosschainTestBase.sol b/test/CrosschainTestBase.sol index 22f778a..773365b 100644 --- a/test/CrosschainTestBase.sol +++ b/test/CrosschainTestBase.sol @@ -35,12 +35,12 @@ abstract contract CrosschainTestBase is Test { event TestEvent(); - address constant L1_EXECUTOR = 0x3300f198988e4C9C63F75dF86De36421f06af8c4; + address constant L1_SPARK_PROXY = 0x3300f198988e4C9C63F75dF86De36421f06af8c4; address constant L1_PAUSE_PROXY = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB; address GUARDIAN = makeAddr('guardian'); L2BridgeExecutorArguments defaultL2BridgeExecutorArgs = L2BridgeExecutorArguments({ - ethereumGovernanceExecutor: L1_EXECUTOR, + ethereumGovernanceExecutor: L1_SPARK_PROXY, delay: 600, gracePeriod: 1200, guardian: GUARDIAN @@ -86,7 +86,7 @@ abstract contract CrosschainTestBase is Test { ); vm.prank(L1_PAUSE_PROXY); - IL1Executor(L1_EXECUTOR).exec( + IL1Executor(L1_SPARK_PROXY).exec( address(crosschainPayload), abi.encodeWithSelector(IPayload.execute.selector) ); @@ -335,7 +335,7 @@ abstract contract CrosschainTestBase is Test { ); vm.prank(L1_PAUSE_PROXY); - IL1Executor(L1_EXECUTOR).exec( + IL1Executor(L1_SPARK_PROXY).exec( address(crosschainPayload), abi.encodeWithSelector(IPayload.execute.selector) ); diff --git a/test/Deploy.t.sol b/test/Deploy.t.sol new file mode 100644 index 0000000..8affd8b --- /dev/null +++ b/test/Deploy.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import 'forge-std/Test.sol'; + +import { OptimismReceiver } from 'lib/xchain-helpers/src/receivers/OptimismReceiver.sol'; + +import { Deploy } from "../deploy/Deploy.sol"; + +import { Executor } from 'src/Executor.sol'; + +contract DeployTests is Test { + + function test_deployExecutor() public { + Executor executor = Executor(Deploy.deployExecutor(100, 1000)); + + assertEq(executor.delay(), 100); + assertEq(executor.gracePeriod(), 1000); + } + + function test_deployOptimismReceiver() public { + OptimismReceiver receiver = OptimismReceiver( + Deploy.deployOptimismReceiver(makeAddr("l1Authority"), makeAddr("executor")) + ); + + assertEq(OptimismReceiver(receiver).l1Authority(), makeAddr("l1Authority")); + assertEq(OptimismReceiver(receiver).target(), makeAddr("executor")); + } + + function test_setUpExecutorPermissions() public { + Executor executor = Executor(Deploy.deployExecutor(100, 1000)); + + OptimismReceiver receiver = OptimismReceiver( + Deploy.deployOptimismReceiver(makeAddr("l1Authority"), makeAddr("executor")) + ); + + address deployer = address(this); + + assertEq(executor.hasRole(executor.SUBMISSION_ROLE(), address(receiver)), false); + assertEq(executor.hasRole(executor.DEFAULT_ADMIN_ROLE(), address(this)), true); + + Deploy.setUpExecutorPermissions(address(executor), address(receiver), deployer); + + assertEq(executor.hasRole(executor.SUBMISSION_ROLE(), address(receiver)), true); + assertEq(executor.hasRole(executor.DEFAULT_ADMIN_ROLE(), address(this)), false); + } + +}