From e39b4d0202094f1beabb7d5357dc5e6d7a0be835 Mon Sep 17 00:00:00 2001 From: excaliborr <excalibor@defi.sucks> Date: Fri, 24 Nov 2023 09:39:46 -0500 Subject: [PATCH] chore: deploying contracts to local node --- package.json | 2 +- proofs/generate_proof.py | 19 +- proofs/proof.json | 6 + proofs/proof_utils.py | 2 +- .../libraries/MerklePatriciaProofVerifier.sol | 18 +- solidity/scripts/DeployE2E.s.sol | 106 ++++-- solidity/scripts/HomeChainDeployments.json | 6 +- solidity/scripts/NonHomeChainDeployments.json | 14 +- solidity/scripts/SafeDeployments.json | 10 + solidity/test/e2e/Common.sol | 335 ++++++++++-------- solidity/test/e2e/VerifierModule.t.sol | 25 +- 11 files changed, 320 insertions(+), 223 deletions(-) create mode 100644 proofs/proof.json create mode 100644 solidity/scripts/SafeDeployments.json diff --git a/package.json b/package.json index 7710ccf..6577237 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "scripts": { "anvil:mainnet": "anvil --port 8545 -f $MAINNET_RPC --fork-block-number 18621047 --chain-id 1", "anvil:optimism": "anvil --port 9545 -f $OPTIMISM_RPC --fork-block-number 112491451 --chain-id 10", - "build": "forge build", + "build": "forge build --via-ir", "build:optimized": "FOUNDRY_PROFILE=optimized forge build", "coverage": "forge coverage --match-contract Unit", "deploy:goerli": "bash -c 'source .env && forge script -vv --rpc-url $GOERLI_RPC --slow --broadcast --private-key $DEPLOYER_GOERLI_PRIVATE_KEY solidity/scripts/DeployGoerli.s.sol:DeployGoerli'", diff --git a/proofs/generate_proof.py b/proofs/generate_proof.py index e517291..cdcdefb 100644 --- a/proofs/generate_proof.py +++ b/proofs/generate_proof.py @@ -10,10 +10,6 @@ def main(): description="Patricia Merkle Trie Proof Generating Tool", formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-b", "--block-number", - type=int, - help="Block number, defaults to `latest - 15`") - parser.add_argument("-r", "--rpc", default="http://localhost:8545", type=str, @@ -29,13 +25,16 @@ def main(): # Save command line arguments into variables args = parser.parse_args() - + + mine_anvil_block(args.rpc) + rpc_endpoint = args.rpc - block_number = args.block_number + 1 + block_number = "latest" storage_mirror_contract_address = args.contract storage_slot = args.slot clean_storage_slot = bytes.fromhex(storage_slot[2:]) - + + mine_anvil_block(rpc_endpoint) # Generate proof data (block_number, block_header, acct_proof, storage_proofs) = generate_proof_data(rpc_endpoint, block_number, storage_mirror_contract_address, [clean_storage_slot]) @@ -52,7 +51,11 @@ def main(): "storageProof": storage_proof.hex() } - print(json.dumps(output)) + # Serializing json + json_object = json.dumps(output, indent=4) + + with open("./proofs/proof.json", "w") as outfile: + outfile.write(json_object) def generate_proof_data( rpc_endpoint, diff --git a/proofs/proof.json b/proofs/proof.json new file mode 100644 index 0000000..94369e5 --- /dev/null +++ b/proofs/proof.json @@ -0,0 +1,6 @@ +{ + "blockNumber": 23, + "blockHeader": "f901f5a098025019b679c7d07a94be981c4d89dfd7e181ab0a6bf552ebbbd8b79c0d5e43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fa44db5328a4efcd29a62fc7256bd65991b619bf92a388bdd98a0671a4d92757a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000178401c9c38000846560aaa180a0b6f10f40b56cdd7e601090ad40d430220882d56a6b4833d4c821f6faca31d7b4880000000000000000", + "accountProof": "f9025ff901f1a08612f63b7f9a11408e2f23f321e5136d332dd57790ed36735777b23957310993a016ef7dfdd5a2499becbb81956a38788bfc057f9d52dd5c576ebcb85de995040ea030235cd697b3c3a0f85fa35fad88d3fc176fa60cd74b1d3cd7add06250b40305a0153a661f74405ad9d8f5d1df1138e82bfef064d71da5eec6df62aedf25868aeba0de26cb1b4fd99c4d3ed75d4a67931e3c252605c7d68e0148d5327f341bfd5283a0409e3997e67d3963cccc4b306dbf32d9b4790db921fe414a1be1030c5327e27ca0865d7ca964ec30d14b72f9744bad3e9f4cd12f3ee0eabfa5b7bf4e3a13c0753e80a0ea85562bb917489f2aa6151418d9c34428721c7d8e3ebd8fb07404a1ef5217fba0650baffbb20b2e9ff377c5518cf910c01caeeb7bc32907c60cda835edb70dff1a07ea03eb36e3087a210f9e1fb8e56dc0ccb528b59e1637443139e5a18312c238da0b584f3ace57d374da950843baaf0c847348d627c4cd625dd66e5dcc41fffffdaa0b6e213ee6b464afba5190eef562a503a089087df5bf722f694bfcc0709413968a0a5ac64bb99d260ef6b13a4f2040ed48a4936664ec13d400238b5004841a4d888a02cced9104a6e072cfcff4bc51d16ad481678fc128ebea28446a982234c65227ba0efc69d2819d03c1d5c708bf8f59905a501ed8d23ef08fb1270cfb345221f28da80f869a034b14a79c7136d5a01f70ed75f70e07b9dbd7d85dc331e9404805af6671a9d96b846f8440180a076f4ebdb9e788380676986fe28d3997be29c3492d9f3f666c9ed91891306beb0a0fd79d9f0b0ab6ee2f4166bb9632d934d81e28cd5fdb396e3f3e06ef9580cfd32", + "storageProof": "f846f844a120de506b3ca792e2f384432fef433a68be75fe11a8028a454651f138569ff3d1e0a1a0a362927a7b493db164d1728c370827794def1c9f44b655434ab20f05d39e7478" +} \ No newline at end of file diff --git a/proofs/proof_utils.py b/proofs/proof_utils.py index aaea6be..165cdcc 100644 --- a/proofs/proof_utils.py +++ b/proofs/proof_utils.py @@ -28,7 +28,7 @@ def request_block_header(rpc_endpoint, block_number): def mine_anvil_block(rpc_endpoint): r = requests.post(rpc_endpoint, json={ "jsonrpc": "2.0", - "method": "anvil_mine", + "method": "evm_mine", "params": [], "id": 1, }) diff --git a/solidity/libraries/MerklePatriciaProofVerifier.sol b/solidity/libraries/MerklePatriciaProofVerifier.sol index c1d090c..865f695 100644 --- a/solidity/libraries/MerklePatriciaProofVerifier.sol +++ b/solidity/libraries/MerklePatriciaProofVerifier.sol @@ -51,12 +51,12 @@ library MerklePatriciaProofVerifier { // The root node is hashed with Keccak-256 ... if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) { - revert(); + revert('revert'); } // ... whereas all other nodes are hashed with the MPT // hash function. if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) { - revert(); + revert('revert 2'); } // We verified that stack[i] has the correct hash, so we // may safely decode it. @@ -87,7 +87,7 @@ library MerklePatriciaProofVerifier { // Sanity check if (i < stack.length - 1) { // divergent node must come last in proof - revert(); + revert('revert 3'); } return new bytes(0); @@ -97,7 +97,7 @@ library MerklePatriciaProofVerifier { // Sanity check if (i < stack.length - 1) { // leaf node must come last in proof - revert(); + revert('revert 4'); } if (mptKeyOffset < mptKey.length) { @@ -111,7 +111,7 @@ library MerklePatriciaProofVerifier { // Sanity check if (i == stack.length - 1) { // shouldn't be at last level - revert(); + revert('revert 5'); } if (!node[1].isList()) { @@ -133,14 +133,14 @@ library MerklePatriciaProofVerifier { mptKeyOffset += 1; if (nibble >= 16) { // each element of the path has to be a nibble - revert(); + revert('revert 6'); } if (_isEmptyBytesequence(node[nibble])) { // Sanity if (i != stack.length - 1) { // leaf node should be at last level - revert(); + revert('revert 7'); } return new bytes(0); @@ -155,7 +155,7 @@ library MerklePatriciaProofVerifier { // Sanity if (i != stack.length - 1) { // should be at last level - revert(); + revert('revert 8'); } return node[16].toBytes(); @@ -211,7 +211,7 @@ library MerklePatriciaProofVerifier { isLeaf = true; } else { // Not supposed to happen! - revert(); + revert('revert'); } return (isLeaf, _decodeNibbles(compact, skipNibbles)); } diff --git a/solidity/scripts/DeployE2E.s.sol b/solidity/scripts/DeployE2E.s.sol index 5bd74f5..c1acedd 100644 --- a/solidity/scripts/DeployE2E.s.sol +++ b/solidity/scripts/DeployE2E.s.sol @@ -5,6 +5,8 @@ import {Script} from 'forge-std/Script.sol'; import {console} from 'forge-std/console.sol'; import {stdJson} from 'forge-std/StdJson.sol'; import {Enum} from 'safe-contracts/common/Enum.sol'; +import {SafeProxy} from 'safe-contracts/proxies/SafeProxy.sol'; +import {Safe} from 'safe-contracts/Safe.sol'; import {DeployHomeChain, DeployVars} from 'scripts/DeployHomeChain.s.sol'; import {DeployNonHomeChain, DeployVarsNonHomeChain} from 'scripts/DeployNonHomeChain.s.sol'; @@ -17,22 +19,30 @@ import {IStorageMirror} from 'interfaces/IStorageMirror.sol'; import {IBlockHeaderOracle} from 'interfaces/IBlockHeaderOracle.sol'; import {IGnosisSafeProxyFactory} from 'test/e2e/IGnosisSafeProxyFactory.sol'; +struct Signature { + uint8 v; + bytes32 r; + bytes32 s; +} + contract DeployE2E is Script, DeployHomeChain, DeployNonHomeChain { address internal _deployer = vm.rememberKey(vm.envUint('MAINNET_DEPLOYER_PK')); uint256 internal _pk = vm.envUint('MAINNET_DEPLOYER_PK'); - IGnosisSafeProxyFactory public gnosisSafeProxyFactory = IGnosisSafeProxyFactory(GNOSIS_SAFE_PROXY_FACTORY); address[] internal _owners = [_deployer]; + Safe internal _singletonSafe; + IVerifierModule.SafeTxnParams internal _vars; function run() external { vm.createSelectFork(vm.rpcUrl('mainnet_e2e')); vm.startBroadcast(_deployer); + _singletonSafe = new Safe(); DeployVars memory _deployVarsHomeChain = DeployVars(_deployer); // Deploy protocol _deployHomeChain(_deployVarsHomeChain); - ISafe _safe = ISafe(address(gnosisSafeProxyFactory.createProxy(GNOSIS_SAFE_SINGLETON, ''))); + ISafe _safe = ISafe(address(new SafeProxy(address(_singletonSafe)))); address _storageMirrorAddr = - vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments2.json'), '$.StorageMirror'); + vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments.json'), '$.StorageMirror'); _setupHomeChain(_safe, _storageMirrorAddr); @@ -47,6 +57,14 @@ contract DeployE2E is Script, DeployHomeChain, DeployNonHomeChain { _deployNonHomeChain(_deployVarsNonHomeChain); vm.stopBroadcast(); + + string memory _objectKey = 'deployments'; + + string memory _output = vm.serializeAddress(_objectKey, 'Safe', address(_safe)); + + vm.writeJson(_output, './solidity/scripts/SafeDeployments.json'); + + // saveProof(vm.rpcUrl('mainnet_e2e'), vm.toString(_storageMirrorAddr), vm.toString((keccak256(abi.encode(address(_safe), 0))))); } /** @@ -95,20 +113,35 @@ contract DeployE2E is Script, DeployHomeChain, DeployNonHomeChain { _safe.nonce() ); + Signature memory _signature; + // signature - (uint8 _v, bytes32 _r, bytes32 _s) = vm.sign(_pk, keccak256(_txData)); + (_signature.v, _signature.r, _signature.s) = vm.sign(_pk, keccak256(_txData)); + + _vars = IVerifierModule.SafeTxnParams({ + to: address(_guardCallbackModule), + value: 0, + data: abi.encodeWithSelector(IGuardCallbackModule.setGuard.selector), + operation: Enum.Operation.Call, + safeTxGas: 0, + baseGas: 0, + gasPrice: 0, + gasToken: address(0), + refundReceiver: payable(address(0)), + signatures: abi.encodePacked(_signature.r, _signature.s, _signature.v) + }); _safe.execTransaction( - _guardCallbackModule, - 0, - abi.encodeWithSelector(IGuardCallbackModule.setGuard.selector), - Enum.Operation.Call, - 0, - 0, - 0, - address(0), - payable(0), - abi.encodePacked(_r, _s, _v) + _vars.to, + _vars.value, + _vars.data, + _vars.operation, + _vars.safeTxGas, + _vars.baseGas, + _vars.gasPrice, + _vars.gasToken, + _vars.refundReceiver, + _vars.signatures ); _txData = _safe.encodeTransactionData( @@ -125,20 +158,43 @@ contract DeployE2E is Script, DeployHomeChain, DeployNonHomeChain { ); // signature - (_v, _r, _s) = vm.sign(_pk, keccak256(_txData)); + (_signature.v, _signature.r, _signature.s) = vm.sign(_pk, keccak256(_txData)); + + _vars.to = _storageMirrorAddr; + _vars.data = abi.encodeWithSelector(IStorageMirror.update.selector, keccak256(abi.encode(_owners, 1))); + _vars.signatures = abi.encodePacked(_signature.r, _signature.s, _signature.v); // execute update storage mirror _safe.execTransaction( - _storageMirrorAddr, - 0, - abi.encodeWithSelector(IStorageMirror.update.selector, keccak256(abi.encode(_owners, 1))), - Enum.Operation.Call, - 0, - 0, - 0, - address(0), - payable(0), - abi.encodePacked(_r, _s, _v) + _vars.to, + _vars.value, + _vars.data, + _vars.operation, + _vars.safeTxGas, + _vars.baseGas, + _vars.gasPrice, + _vars.gasToken, + _vars.refundReceiver, + _vars.signatures ); } + + // function saveProof( + // string memory _rpc, + // string memory _contractAddress, + // string memory _storageSlot + // ) public { + // string[] memory _commands = new string[](8); + // _commands[0] = 'yarn'; + // _commands[1] = 'proof'; + // _commands[2] = '--rpc'; + // _commands[3] = _rpc; + // _commands[4] = '--contract'; + // _commands[5] = _contractAddress; + // _commands[6] = '--slot'; + // _commands[7] = _storageSlot; + + // bytes memory _res = vm.ffi(_commands); + // string memory _output = string(_res); + // } } diff --git a/solidity/scripts/HomeChainDeployments.json b/solidity/scripts/HomeChainDeployments.json index 23841f2..9af81ff 100644 --- a/solidity/scripts/HomeChainDeployments.json +++ b/solidity/scripts/HomeChainDeployments.json @@ -1,5 +1,5 @@ { - "GuardCallbackModule": "0x15BB2cc3Ea43ab2658F7AaecEb78A9d3769BE3cb", - "StorageMirror": "0xCdb63c58b907e76872474A0597C5252eDC97c883", - "UpdateStorageMirrorGuard": "0xa4d0806d597146df93796A38435ABB2a3cb96677" + "GuardCallbackModule": "0x15C31F52d65867015E99690Ee17438C5c5C187A6", + "StorageMirror": "0xd1132644779978752075ec0d8E3A4B206bd80420", + "UpdateStorageMirrorGuard": "0x4974711198287D8058dc4a866E5F5f13B5fB11fF" } \ No newline at end of file diff --git a/solidity/scripts/NonHomeChainDeployments.json b/solidity/scripts/NonHomeChainDeployments.json index 7305017..d9291de 100644 --- a/solidity/scripts/NonHomeChainDeployments.json +++ b/solidity/scripts/NonHomeChainDeployments.json @@ -1,9 +1,9 @@ { - "BlockHeaderOracle": "0x3347B4d90ebe72BeFb30444C9966B2B990aE9FcB", - "GuardCallbackModule": "0x889D9A5AF83525a2275e41464FAECcCb3337fF60", - "NeedsUpdateGuard": "0xffa7CA1AEEEbBc30C874d32C7e22F052BbEa0429", - "StorageMirror": "0x9852795dbb01913439f534b4984fBf74aC8AfA12", - "StorageMirrorRootRegistry": "0x5bf5b11053e734690269C6B9D438F8C9d48F528A", - "UpdateStorageMirrorGuard": "0xf274De14171Ab928A5Ec19928cE35FaD91a42B64", - "VerifierModule": "0x3155755b79aA083bd953911C92705B7aA82a18F9" + "BlockHeaderOracle": "0x35405D4CED44D7370f4a868165612D020eDa57Ad", + "GuardCallbackModule": "0x15C31F52d65867015E99690Ee17438C5c5C187A6", + "NeedsUpdateGuard": "0x9f24e39DAa3F15D2A261d3e8ec84867D93c655Ff", + "StorageMirror": "0xd1132644779978752075ec0d8E3A4B206bd80420", + "StorageMirrorRootRegistry": "0x62eE67efd6780364dD9c9555FD96859327AFE895", + "UpdateStorageMirrorGuard": "0x4974711198287D8058dc4a866E5F5f13B5fB11fF", + "VerifierModule": "0xBE081bf326F43c17d27b8a47bC5F32Aeb8b036B7" } \ No newline at end of file diff --git a/solidity/scripts/SafeDeployments.json b/solidity/scripts/SafeDeployments.json new file mode 100644 index 0000000..1fad435 --- /dev/null +++ b/solidity/scripts/SafeDeployments.json @@ -0,0 +1,10 @@ +{ + "BlockHeaderOracle": "0x35405D4CED44D7370f4a868165612D020eDa57Ad", + "GuardCallbackModule": "0x15C31F52d65867015E99690Ee17438C5c5C187A6", + "NeedsUpdateGuard": "0x9f24e39DAa3F15D2A261d3e8ec84867D93c655Ff", + "Safe": "0x1cCc7fae21A35605AA7031AE6FBf2f304B80aC4D", + "StorageMirror": "0xd1132644779978752075ec0d8E3A4B206bd80420", + "StorageMirrorRootRegistry": "0x62eE67efd6780364dD9c9555FD96859327AFE895", + "UpdateStorageMirrorGuard": "0x4974711198287D8058dc4a866E5F5f13B5fB11fF", + "VerifierModule": "0xBE081bf326F43c17d27b8a47bC5F32Aeb8b036B7" +} \ No newline at end of file diff --git a/solidity/test/e2e/Common.sol b/solidity/test/e2e/Common.sol index 634cf6d..1d22a5c 100644 --- a/solidity/test/e2e/Common.sol +++ b/solidity/test/e2e/Common.sol @@ -60,159 +60,185 @@ contract CommonE2EBase is DSTestPlus, TestConstants, Script { _commands[1] = 'script'; _commands[2] = 'solidity/scripts/DeployE2E.s.sol:DeployE2E'; _commands[3] = '--broadcast'; - _commands[4] = '--via-ir'; + _commands[4] = '--ffi'; vm.ffi(_commands); - // NOTE: BELOW IS UNNECCESARY LOGIC I JUST HAVENT REMOVED IT YET - // Set up both forks - _mainnetForkId = vm.createSelectFork(vm.rpcUrl('mainnet_e2e'), _MAINNET_FORK_BLOCK); - _optimismForkId = vm.createSelectFork(vm.rpcUrl('optimism_e2e'), _OPTIMISM_FORK_BLOCK); - // Select mainnet fork - vm.selectFork(_mainnetForkId); - - // Make address and key of safe owner - safeOwner = vm.envAddress('MAINNET_SAFE_OWNER_ADDR'); - safeOwnerKey = vm.envUint('MAINNET_SAFE_OWNER_PK'); - - // Make address and key of deployer - deployer = vm.envAddress('MAINNET_DEPlOYER_ADDR'); - deployerKey = vm.envUint('MAINNET_DEPLOYER_PK'); - - /// =============== HOME CHAIN =============== - vm.broadcast(safeOwnerKey); - safe = ISafe(address(gnosisSafeProxyFactory.createProxy(GNOSIS_SAFE_SINGLETON, ''))); // safeOwner nonce 0 - label(address(safe), 'SafeProxy'); - - uint256 _nonce = vm.getNonce(deployer); - - address _updateStorageMirrorGuardTheoriticalAddress = ContractDeploymentAddress.addressFrom(deployer, _nonce + 2); - - vm.broadcast(deployer); - storageMirror = new StorageMirror(); // deployer nonce 0 - label(address(storageMirror), 'StorageMirror'); + _mainnetForkId = vm.createSelectFork(vm.rpcUrl('mainnet_e2e')); + _optimismForkId = vm.createSelectFork(vm.rpcUrl('optimism_e2e')); - vm.broadcast(deployer); - guardCallbackModule = new GuardCallbackModule(address(storageMirror), _updateStorageMirrorGuardTheoriticalAddress); // deployer nonce 1 - label(address(guardCallbackModule), 'GuardCallbackModule'); - - vm.broadcast(deployer); - updateStorageMirrorGuard = new UpdateStorageMirrorGuard(guardCallbackModule); // deployer nonce 2 - label(address(updateStorageMirrorGuard), 'UpdateStorageMirrorGuard'); - - // Make sure the theoritical address was calculated correctly - assert(address(updateStorageMirrorGuard) == _updateStorageMirrorGuardTheoriticalAddress); - - // Set up owner home chain safe - address[] memory _owners = new address[](1); - _owners[0] = safeOwner; - vm.broadcast(safeOwnerKey); // safeOwner nonce 1 - safe.setup(_owners, 1, address(safe), bytes(''), address(0), address(0), 0, payable(0)); - - // Enable guard callback module - enableModule(safe, safeOwnerKey, address(guardCallbackModule)); - - // data to sign and send to set the guard - bytes memory _setGuardData = abi.encodeWithSelector(IGuardCallbackModule.setGuard.selector); - bytes memory _setGuardEncodedTxData = safe.encodeTransactionData( - address(guardCallbackModule), 0, _setGuardData, Enum.Operation.Call, 0, 0, 0, address(0), payable(0), safe.nonce() + storageMirror = + StorageMirror(vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments.json'), '$.StorageMirror')); + updateStorageMirrorGuard = UpdateStorageMirrorGuard( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments.json'), '$.UpdateStorageMirrorGuard') ); - - // signature - (uint8 _v, bytes32 _r, bytes32 _s) = vm.sign(safeOwnerKey, keccak256(_setGuardEncodedTxData)); - bytes memory _setGuardSignature = abi.encodePacked(_r, _s, _v); - - // execute setup of guard - vm.broadcast(safeOwnerKey); - safe.execTransaction( - address(guardCallbackModule), - 0, - _setGuardData, - Enum.Operation.Call, - 0, - 0, - 0, - address(0), - payable(0), - _setGuardSignature + guardCallbackModule = GuardCallbackModule( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments.json'), '$.GuardCallbackModule') ); - - /// =============== NON HOME CHAIN =============== - vm.selectFork(_optimismForkId); - // Make address and key of non home chain safe owner - (nonHomeChainSafeOwner, nonHomeChainSafeOwnerKey) = makeAddrAndKey('nonHomeChainSafeOwner'); - - address _storageMirrorRootRegistryTheoriticalAddress = ContractDeploymentAddress.addressFrom(deployerOptimism, 2); - - // Set up non home chain safe - vm.broadcast(nonHomeChainSafeOwnerKey); - nonHomeChainSafe = ISafe(address(gnosisSafeProxyFactory.createProxy(GNOSIS_SAFE_SINGLETON_L2, ''))); // nonHomeChainSafeOwner nonce 0 - label(address(nonHomeChainSafe), 'NonHomeChainSafeProxy'); - - // Deploy non home chain contracts - oracle = new BlockHeaderOracle(); // deployerOptimism nonce 0 - label(address(oracle), 'BlockHeaderOracle'); - - vm.broadcast(deployerOptimism); - verifierModule = - new VerifierModule(IStorageMirrorRootRegistry(_storageMirrorRootRegistryTheoriticalAddress), address(storageMirror)); // deployerOptimism nonce 1 - label(address(verifierModule), 'VerifierModule'); - - vm.broadcast(deployerOptimism); - storageMirrorRootRegistry = - new StorageMirrorRootRegistry(address(storageMirror), IVerifierModule(verifierModule), IBlockHeaderOracle(oracle)); // deployerOptimism nonce 2 - label(address(storageMirrorRootRegistry), 'StorageMirrorRootRegistry'); - - vm.broadcast(deployerOptimism); - needsUpdateGuard = new NeedsUpdateGuard(verifierModule); // deployer nonce 3 - label(address(needsUpdateGuard), 'NeedsUpdateGuard'); - - // set up non home chain safe - address[] memory _nonHomeChainSafeOwners = new address[](1); - _nonHomeChainSafeOwners[0] = nonHomeChainSafeOwner; - - vm.broadcast(nonHomeChainSafeOwnerKey); // nonHomeChainSafeOwner nonce 1 - nonHomeChainSafe.setup( - _nonHomeChainSafeOwners, 1, address(nonHomeChainSafe), bytes(''), address(0), address(0), 0, payable(0) + oracle = BlockHeaderOracle( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/NonHomeChainDeployments.json'), '$.BlockHeaderOracle') ); - - // enable verifier module - enableModule(nonHomeChainSafe, nonHomeChainSafeOwnerKey, address(verifierModule)); - - // data to sign and send to set the guard - _setGuardData = abi.encodeWithSelector(ISafe.setGuard.selector, address(needsUpdateGuard)); - _setGuardEncodedTxData = nonHomeChainSafe.encodeTransactionData( - address(nonHomeChainSafe), - 0, - _setGuardData, - Enum.Operation.Call, - 0, - 0, - 0, - address(0), - payable(0), - nonHomeChainSafe.nonce() + needsUpdateGuard = NeedsUpdateGuard( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/NonHomeChainDeployments.json'), '$.NeedsUpdateGuard') ); - - // signature - (_v, _r, _s) = vm.sign(nonHomeChainSafeOwnerKey, keccak256(_setGuardEncodedTxData)); - _setGuardSignature = abi.encodePacked(_r, _s, _v); - - // set needs update guard - vm.broadcast(nonHomeChainSafeOwnerKey); - nonHomeChainSafe.execTransaction( - address(nonHomeChainSafe), - 0, - _setGuardData, - Enum.Operation.Call, - 0, - 0, - 0, - address(0), - payable(0), - _setGuardSignature + verifierModule = VerifierModule( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/NonHomeChainDeployments.json'), '$.VerifierModule') + ); + storageMirrorRootRegistry = StorageMirrorRootRegistry( + vm.parseJsonAddress(vm.readFile('./solidity/scripts/NonHomeChainDeployments.json'), '$.StorageMirrorRootRegistry') ); + safe = ISafe(vm.parseJsonAddress(vm.readFile('./solidity/scripts/SafeDeployments.json'), '$.Safe')); + + // NOTE: BELOW IS UNNECCESARY LOGIC I JUST HAVENT REMOVED IT YET + + // Set up both forks + // _mainnetForkId = vm.createSelectFork(vm.rpcUrl('mainnet_e2e')); + // _optimismForkId = vm.createSelectFork(vm.rpcUrl('optimism_e2e')); + // // Select mainnet fork + // vm.selectFork(_mainnetForkId); + + // // Make address and key of safe owner + // safeOwner = vm.envAddress('MAINNET_SAFE_OWNER_ADDR'); + // safeOwnerKey = vm.envUint('MAINNET_SAFE_OWNER_PK'); + + // // Make address and key of deployer + // deployer = vm.envAddress('MAINNET_DEPlOYER_ADDR'); + // deployerKey = vm.envUint('MAINNET_DEPLOYER_PK'); + + // /// =============== HOME CHAIN =============== + // vm.broadcast(safeOwnerKey); + // safe = ISafe(address(gnosisSafeProxyFactory.createProxy(GNOSIS_SAFE_SINGLETON, ''))); // safeOwner nonce 0 + // label(address(safe), 'SafeProxy'); + + // uint256 _nonce = vm.getNonce(deployer); + + // address _updateStorageMirrorGuardTheoriticalAddress = ContractDeploymentAddress.addressFrom(deployer, _nonce + 2); + + // vm.broadcast(deployer); + // storageMirror = new StorageMirror(); // deployer nonce 0 + // label(address(storageMirror), 'StorageMirror'); + + // vm.broadcast(deployer); + // guardCallbackModule = new GuardCallbackModule(address(storageMirror), _updateStorageMirrorGuardTheoriticalAddress); // deployer nonce 1 + // label(address(guardCallbackModule), 'GuardCallbackModule'); + + // vm.broadcast(deployer); + // updateStorageMirrorGuard = new UpdateStorageMirrorGuard(guardCallbackModule); // deployer nonce 2 + // label(address(updateStorageMirrorGuard), 'UpdateStorageMirrorGuard'); + + // // Make sure the theoritical address was calculated correctly + // assert(address(updateStorageMirrorGuard) == _updateStorageMirrorGuardTheoriticalAddress); + + // // Set up owner home chain safe + // address[] memory _owners = new address[](1); + // _owners[0] = safeOwner; + // vm.broadcast(safeOwnerKey); // safeOwner nonce 1 + // safe.setup(_owners, 1, address(safe), bytes(''), address(0), address(0), 0, payable(0)); + + // // Enable guard callback module + // enableModule(safe, safeOwnerKey, address(guardCallbackModule)); + + // // data to sign and send to set the guard + // bytes memory _setGuardData = abi.encodeWithSelector(IGuardCallbackModule.setGuard.selector); + // bytes memory _setGuardEncodedTxData = safe.encodeTransactionData( + // address(guardCallbackModule), 0, _setGuardData, Enum.Operation.Call, 0, 0, 0, address(0), payable(0), safe.nonce() + // ); + + // // signature + // (uint8 _v, bytes32 _r, bytes32 _s) = vm.sign(safeOwnerKey, keccak256(_setGuardEncodedTxData)); + // bytes memory _setGuardSignature = abi.encodePacked(_r, _s, _v); + + // // execute setup of guard + // vm.broadcast(safeOwnerKey); + // safe.execTransaction( + // address(guardCallbackModule), + // 0, + // _setGuardData, + // Enum.Operation.Call, + // 0, + // 0, + // 0, + // address(0), + // payable(0), + // _setGuardSignature + // ); + + // /// =============== NON HOME CHAIN =============== + // vm.selectFork(_optimismForkId); + // // Make address and key of non home chain safe owner + // (nonHomeChainSafeOwner, nonHomeChainSafeOwnerKey) = makeAddrAndKey('nonHomeChainSafeOwner'); + + // address _storageMirrorRootRegistryTheoriticalAddress = ContractDeploymentAddress.addressFrom(deployerOptimism, 2); + + // // Set up non home chain safe + // vm.broadcast(nonHomeChainSafeOwnerKey); + // nonHomeChainSafe = ISafe(address(gnosisSafeProxyFactory.createProxy(GNOSIS_SAFE_SINGLETON_L2, ''))); // nonHomeChainSafeOwner nonce 0 + // label(address(nonHomeChainSafe), 'NonHomeChainSafeProxy'); + + // // Deploy non home chain contracts + // oracle = new BlockHeaderOracle(); // deployerOptimism nonce 0 + // label(address(oracle), 'BlockHeaderOracle'); + + // vm.broadcast(deployerOptimism); + // verifierModule = + // new VerifierModule(IStorageMirrorRootRegistry(_storageMirrorRootRegistryTheoriticalAddress), address(storageMirror)); // deployerOptimism nonce 1 + // label(address(verifierModule), 'VerifierModule'); + + // vm.broadcast(deployerOptimism); + // storageMirrorRootRegistry = + // new StorageMirrorRootRegistry(address(storageMirror), IVerifierModule(verifierModule), IBlockHeaderOracle(oracle)); // deployerOptimism nonce 2 + // label(address(storageMirrorRootRegistry), 'StorageMirrorRootRegistry'); + + // vm.broadcast(deployerOptimism); + // needsUpdateGuard = new NeedsUpdateGuard(verifierModule); // deployer nonce 3 + // label(address(needsUpdateGuard), 'NeedsUpdateGuard'); + + // // set up non home chain safe + // address[] memory _nonHomeChainSafeOwners = new address[](1); + // _nonHomeChainSafeOwners[0] = nonHomeChainSafeOwner; + + // vm.broadcast(nonHomeChainSafeOwnerKey); // nonHomeChainSafeOwner nonce 1 + // nonHomeChainSafe.setup( + // _nonHomeChainSafeOwners, 1, address(nonHomeChainSafe), bytes(''), address(0), address(0), 0, payable(0) + // ); + + // // enable verifier module + // enableModule(nonHomeChainSafe, nonHomeChainSafeOwnerKey, address(verifierModule)); + + // // data to sign and send to set the guard + // _setGuardData = abi.encodeWithSelector(ISafe.setGuard.selector, address(needsUpdateGuard)); + // _setGuardEncodedTxData = nonHomeChainSafe.encodeTransactionData( + // address(nonHomeChainSafe), + // 0, + // _setGuardData, + // Enum.Operation.Call, + // 0, + // 0, + // 0, + // address(0), + // payable(0), + // nonHomeChainSafe.nonce() + // ); + + // // signature + // (_v, _r, _s) = vm.sign(nonHomeChainSafeOwnerKey, keccak256(_setGuardEncodedTxData)); + // _setGuardSignature = abi.encodePacked(_r, _s, _v); + + // // set needs update guard + // vm.broadcast(nonHomeChainSafeOwnerKey); + // nonHomeChainSafe.execTransaction( + // address(nonHomeChainSafe), + // 0, + // _setGuardData, + // Enum.Operation.Call, + // 0, + // 0, + // 0, + // address(0), + // payable(0), + // _setGuardSignature + // ); } /** @@ -241,29 +267,26 @@ contract CommonE2EBase is DSTestPlus, TestConstants, Script { } function getProof( - string memory _blockNumber, string memory _rpc, string memory _contractAddress, string memory _storageSlot ) public returns (bytes memory _storageProof, bytes memory _accountProof, bytes memory _blockHeader) { - string[] memory _commands = new string[](10); + string[] memory _commands = new string[](8); _commands[0] = 'yarn'; _commands[1] = 'proof'; - _commands[2] = '--block-number'; - _commands[3] = _blockNumber; - _commands[4] = '--rpc'; - _commands[5] = _rpc; - _commands[6] = '--contract'; - _commands[7] = _contractAddress; - _commands[8] = '--slot'; - _commands[9] = _storageSlot; + _commands[2] = '--rpc'; + _commands[3] = _rpc; + _commands[4] = '--contract'; + _commands[5] = _contractAddress; + _commands[6] = '--slot'; + _commands[7] = _storageSlot; bytes memory _res = vm.ffi(_commands); string memory _output = string(_res); emit log_string(_output); - _storageProof = vm.parseJson(_output, 'storageProof'); - _blockHeader = vm.parseJson(_output, 'blockHeader'); - _accountProof = vm.parseJson(_output, 'accountProof'); + _storageProof = vm.parseJsonBytes(vm.readFile('./proofs/proof.json'), '$.storageProof'); + _blockHeader = vm.parseJsonBytes(vm.readFile('./proofs/proof.json'), '$.blockHeader'); + _accountProof = vm.parseJsonBytes(vm.readFile('./proofs/proof.json'), '$.accountProof'); } } diff --git a/solidity/test/e2e/VerifierModule.t.sol b/solidity/test/e2e/VerifierModule.t.sol index ae8b729..101bd05 100644 --- a/solidity/test/e2e/VerifierModule.t.sol +++ b/solidity/test/e2e/VerifierModule.t.sol @@ -2,22 +2,21 @@ pragma solidity >=0.8.4 <0.9.0; import {CommonE2EBase} from 'test/e2e/Common.sol'; +import {StateVerifier} from 'libraries/StateVerifier.sol'; contract VerifierModuleE2E is CommonE2EBase { - function setUp() public override { - super.setUp(); - } - - function testProposeAndVerifyUpdate() public { - address _storageMirrorAddr = - vm.parseJsonAddress(vm.readFile('./solidity/scripts/HomeChainDeployments.json'), '$.StorageMirror'); + function testExtractStateRoot() public { + (, bytes memory _accountProof, bytes memory _blockHeader) = getProof( + vm.rpcUrl('mainnet_e2e'), + vm.toString(address(storageMirror)), + vm.toString((keccak256(abi.encode(address(safe), 0)))) + ); + (bytes32 _stateRoot, uint256 _blockNumber) = + verifierModule.extractStorageMirrorStorageRoot(_accountProof, _blockHeader); - string memory _blockNumberString = vm.toString(_MAINNET_FORK_BLOCK); - string memory _rpc = vm.rpcUrl('mainnet_e2e'); - string memory _contract = vm.toString(address(_storageMirrorAddr)); - string memory _slot = vm.toString((keccak256(abi.encode(address(safe), 0)))); + uint256 _expectedBlockNumber = vm.parseJsonUint(vm.readFile('./proofs/proof.json'), '$.blockNumber'); - (bytes memory _storageProof, bytes memory _accountProof, bytes memory _blockHeader) = - getProof(_blockNumberString, _rpc, _contract, _slot); + assertTrue(_stateRoot != bytes32(0)); + assertEq(_blockNumber, _expectedBlockNumber); } }