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);
   }
 }