From 2e77e17b47eec05d7234de9abac11fcf3222787a Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 12 Nov 2024 11:09:29 +0100 Subject: [PATCH 1/5] feat(evm): adds HashiProverUpgradeable and some comments to HashiProver --- packages/evm/contracts/prover/HashiProver.sol | 41 +++ .../prover/HashiProverUpgradeable.sol | 245 +++++++++++++++ .../test/HashiProverTestUpgradeable.sol | 24 ++ packages/evm/hardhat.config.ts | 1 + packages/evm/package.json | 1 + packages/evm/test/05_HashiProver.spec.ts | 293 ++++++++++-------- yarn.lock | 282 ++++++++++++++++- 7 files changed, 736 insertions(+), 151 deletions(-) create mode 100644 packages/evm/contracts/prover/HashiProverUpgradeable.sol create mode 100644 packages/evm/contracts/test/HashiProverTestUpgradeable.sol diff --git a/packages/evm/contracts/prover/HashiProver.sol b/packages/evm/contracts/prover/HashiProver.sol index c975cbfc..59260e5b 100644 --- a/packages/evm/contracts/prover/HashiProver.sol +++ b/packages/evm/contracts/prover/HashiProver.sol @@ -11,6 +11,7 @@ contract HashiProver is IHashiProver { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; + /// @notice Stores the address of the ShoyuBashi contract. address public immutable SHOYU_BASHI; constructor(address shoyuBashi) { @@ -84,6 +85,18 @@ contract HashiProver is IHashiProver { return _verifyStorageProof(proof.storageHash, proof.storageKeys, proof.storageProof); } + /** + * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. + * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. + * If it doesn't match directly, it will verify the block by traversing ancestral blocks until a matching block header or ancestor is found. + * If no match is found, it reverts with `BlockHeaderNotFound`. + * @param chainId The chain ID associated with the block. + * @param blockNumber The number of the block to be checked. + * @param blockHeader The RLP-encoded header of the block. + * @param ancestralBlockNumber The block number of the ancestral block to be verified, if applicable. + * @param ancestralBlockHeaders An array of RLP-encoded headers for ancestral blocks. + * @return bytes The RLP-encoded block header if successfully verified. + */ function _checkBlockHeaderAgainstHashi( uint256 chainId, uint256 blockNumber, @@ -120,6 +133,13 @@ contract HashiProver is IHashiProver { revert BlockHeaderNotFound(); } + /** + * @notice Extracts the fields of a transaction receipt from its RLP-encoded data. + * @dev This function handles different transaction types by setting the appropriate offset for RLP parsing. + * It adjusts the starting point based on the transaction type byte, then uses RLPReader to parse the fields. + * @param value The RLP-encoded transaction receipt. + * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. + */ function _extractReceiptFields(bytes memory value) private pure returns (RLPReader.RLPItem[] memory) { uint256 offset; if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { @@ -138,6 +158,18 @@ contract HashiProver is IHashiProver { return RLPReader.RLPItem(value.length - offset, memPtr).toList(); } + /** + * @notice Verifies an account proof and extracts account fields from it. + * @dev This function uses a Merkle proof to verify the account state in a given state root. + * It retrieves and decodes the account data, checking the storage root and account structure. + * @param account The address of the account to verify. + * @param stateRoot The state root against which the account proof is verified. + * @param proof A Merkle proof required to verify the account. + * @return uint256 The nonce of the account. + * @return uint256 The balance of the account. + * @return bytes32 The storage root of the account. + * @return bytes32 The code hash of the account. + */ function _verifyAccountProof( address account, bytes32 stateRoot, @@ -158,6 +190,15 @@ contract HashiProver is IHashiProver { ); } + /** + * @notice Verifies multiple storage proofs and retrieves the storage values associated with given keys. + * @dev This function iterates over provided storage keys and their respective proofs, + * using a Merkle proof to verify each storage value against the specified storage hash. + * @param storageHash The root hash of the storage trie for the account being verified. + * @param storageKeys An array of storage keys for which values need to be verified. + * @param proof A 2D array of Merkle proof elements for each storage key. + * @return bytes[] An array of storage values corresponding to each storage key. + */ function _verifyStorageProof( bytes32 storageHash, bytes32[] memory storageKeys, diff --git a/packages/evm/contracts/prover/HashiProverUpgradeable.sol b/packages/evm/contracts/prover/HashiProverUpgradeable.sol new file mode 100644 index 00000000..4441a14e --- /dev/null +++ b/packages/evm/contracts/prover/HashiProverUpgradeable.sol @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; +import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; +import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol"; +import { IHashiProver } from "../interfaces/IHashiProver.sol"; +import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; + +contract HashiProverUpgradeable is IHashiProver, Initializable, OwnableUpgradeable { + using RLPReader for RLPReader.RLPItem; + using RLPReader for bytes; + + /// @notice Stores the address of the ShoyuBashi contract. + /// @dev This address can be updated by the owner using the `setShoyuBashi` function. + address public shoyuBashi; + + /** + * @notice Emitted when the ShoyuBashi contract address is updated. + * @param shoyuBashi The new address of the ShoyuBashi contract. + */ + event ShoyuBashiSet(address shoyuBashi); + + function __HashiProverUpgradeable_init(address shoyuBashi_) public onlyInitializing { + __Ownable_init(); + shoyuBashi = shoyuBashi_; + } + + /** + * @notice Sets the address of the ShoyuBashi contract. + * @dev This function can only be called by the contract owner. + * It updates the `shoyuBashi` address and emits an event to record the change. + * @param shoyuBashi_ The new address for the ShoyuBashi contract. + */ + function setShoyuBashi(address shoyuBashi_) external onlyOwner { + shoyuBashi = shoyuBashi_; + emit ShoyuBashiSet(shoyuBashi_); + } + + /** + * @dev Verifies and retrieves a specific event from a transaction receipt in a foreign blockchain. + * + * @param proof A `ReceiptProof` struct containing proof details: + * - chainId: The chain ID of the foreign blockchain. + * - blockNumber: If ancestralBlockNumber is 0, then blockNumber represents the block where the transaction occurred and is available in Hashi. + * - blockHeader: The header of the specified block. + * - ancestralBlockNumber: If provided, this is the block number where the transaction took place. In this case, blockNumber is the block whose header is accessible in Hashi. + * - ancestralBlockHeaders: Array of block headers to prove the ancestry of the specified block. + * - receiptProof: Proof data for locating the receipt in the Merkle Trie. + * - transactionIndex: Index of the transaction within the block. + * - logIndex: The specific log index within the transaction receipt. + * + * @return bytes The RLP-encoded event corresponding to the specified `logIndex`. + */ + function verifyForeignEvent(ReceiptProof calldata proof) internal view returns (bytes memory) { + bytes memory blockHeader = _checkBlockHeaderAgainstHashi( + proof.chainId, + proof.blockNumber, + proof.blockHeader, + proof.ancestralBlockNumber, + proof.ancestralBlockHeaders + ); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); + bytes32 receiptsRoot = bytes32(blockHeaderFields[5].toUint()); + + bytes memory value = MerkleTrie.get(proof.transactionIndex, proof.receiptProof, receiptsRoot); + RLPReader.RLPItem[] memory receiptFields = _extractReceiptFields(value); + if (receiptFields.length != 4) revert InvalidReceipt(); + + RLPReader.RLPItem[] memory logs = receiptFields[3].toList(); + if (proof.logIndex >= logs.length) revert InvalidLogIndex(); + return logs[proof.logIndex].toRlpBytes(); + } + + /** + * @dev Verifies foreign storage data for a specified account on a foreign blockchain. + * + * @param proof An `AccountAndStorageProof` struct containing proof details: + * - chainId: The chain ID of the foreign blockchain. + * - blockNumber: If ancestralBlockNumber is 0, then blockNumber represents the block where the transaction occurred and is available in Hashi. + * - blockHeader: The header of the specified block. + * - ancestralBlockNumber: If provided, this is the block number where the transaction took place. In this case, blockNumber is the block whose header is accessible in Hashi. + * - ancestralBlockHeaders: Array of block headers proving ancestry of the specified block. + * - account: The account address whose storage is being verified. + * - accountProof: Proof data for locating the account in the state trie. + * - storageHash: Expected hash of the storage root for the account. + * - storageKeys: Array of storage keys for which data is being verified. + * - storageProof: Proof data for locating the storage values in the storage trie. + * + * @return bytes[] An array of storage values corresponding to the specified `storageKeys`. + */ + function verifyForeignStorage(AccountAndStorageProof calldata proof) internal view returns (bytes[] memory) { + bytes memory blockHeader = _checkBlockHeaderAgainstHashi( + proof.chainId, + proof.blockNumber, + proof.blockHeader, + proof.ancestralBlockNumber, + proof.ancestralBlockHeaders + ); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); + bytes32 stateRoot = bytes32(blockHeaderFields[3].toUint()); + (, , bytes32 expectedStorageHash, ) = _verifyAccountProof(proof.account, stateRoot, proof.accountProof); + if (proof.storageHash != expectedStorageHash) revert InvalidStorageHash(); + return _verifyStorageProof(proof.storageHash, proof.storageKeys, proof.storageProof); + } + + /** + * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. + * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. + * If it doesn't match directly, it will verify the block by traversing ancestral blocks until a matching block header or ancestor is found. + * If no match is found, it reverts with `BlockHeaderNotFound`. + * @param chainId The chain ID associated with the block. + * @param blockNumber The number of the block to be checked. + * @param blockHeader The RLP-encoded header of the block. + * @param ancestralBlockNumber The block number of the ancestral block to be verified, if applicable. + * @param ancestralBlockHeaders An array of RLP-encoded headers for ancestral blocks. + * @return bytes The RLP-encoded block header if successfully verified. + */ + function _checkBlockHeaderAgainstHashi( + uint256 chainId, + uint256 blockNumber, + bytes memory blockHeader, + uint256 ancestralBlockNumber, + bytes[] memory ancestralBlockHeaders + ) private view returns (bytes memory) { + bytes32 blockHeaderHash = keccak256(blockHeader); + bytes32 currentBlockHeaderHash = IShoyuBashi(shoyuBashi).getThresholdHash(chainId, blockNumber); + if (currentBlockHeaderHash == blockHeaderHash && ancestralBlockHeaders.length == 0) return blockHeader; + + for (uint256 i = 0; i < ancestralBlockHeaders.length; i++) { + RLPReader.RLPItem memory ancestralBlockHeaderRLP = RLPReader.toRlpItem(ancestralBlockHeaders[i]); + RLPReader.RLPItem[] memory ancestralBlockHeaderContent = ancestralBlockHeaderRLP.toList(); + + bytes32 blockParentHash = bytes32(ancestralBlockHeaderContent[0].toUint()); + uint256 currentAncestralBlockNumber = uint256(ancestralBlockHeaderContent[8].toUint()); + + bytes32 ancestralBlockHeaderHash = keccak256(ancestralBlockHeaders[i]); + if (ancestralBlockHeaderHash != currentBlockHeaderHash) + revert ConflictingBlockHeader( + currentAncestralBlockNumber, + ancestralBlockHeaderHash, + currentBlockHeaderHash + ); + + if (ancestralBlockNumber == currentAncestralBlockNumber) { + return ancestralBlockHeaders[i]; + } else { + currentBlockHeaderHash = blockParentHash; + } + } + + revert BlockHeaderNotFound(); + } + + /** + * @notice Extracts the fields of a transaction receipt from its RLP-encoded data. + * @dev This function handles different transaction types by setting the appropriate offset for RLP parsing. + * It adjusts the starting point based on the transaction type byte, then uses RLPReader to parse the fields. + * @param value The RLP-encoded transaction receipt. + * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. + */ + function _extractReceiptFields(bytes memory value) private pure returns (RLPReader.RLPItem[] memory) { + uint256 offset; + if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { + offset = 1; + } else if (value[0] >= 0xc0) { + offset = 0; + } else { + revert UnsupportedTxType(); + } + + uint256 memPtr; + assembly { + memPtr := add(value, add(0x20, mul(0x01, offset))) + } + + return RLPReader.RLPItem(value.length - offset, memPtr).toList(); + } + + /** + * @notice Verifies an account proof and extracts account fields from it. + * @dev This function uses a Merkle proof to verify the account state in a given state root. + * It retrieves and decodes the account data, checking the storage root and account structure. + * @param account The address of the account to verify. + * @param stateRoot The state root against which the account proof is verified. + * @param proof A Merkle proof required to verify the account. + * @return uint256 The nonce of the account. + * @return uint256 The balance of the account. + * @return bytes32 The storage root of the account. + * @return bytes32 The code hash of the account. + */ + function _verifyAccountProof( + address account, + bytes32 stateRoot, + bytes[] memory proof + ) private pure returns (uint256, uint256, bytes32, bytes32) { + bytes memory accountRlp = SecureMerkleTrie.get(abi.encodePacked(account), proof, stateRoot); + + bytes32 accountStorageRoot = bytes32(accountRlp.toRlpItem().toList()[2].toUint()); + if (accountStorageRoot.length == 0) revert InvalidStorageHash(); + RLPReader.RLPItem[] memory accountFields = accountRlp.toRlpItem().toList(); + if (accountFields.length != 4) revert InvalidAccount(); + // [nonce, balance, storageHash, codeHash] + return ( + accountFields[0].toUint(), + accountFields[1].toUint(), + bytes32(accountFields[2].toUint()), + bytes32(accountFields[3].toUint()) + ); + } + + /** + * @notice Verifies multiple storage proofs and retrieves the storage values associated with given keys. + * @dev This function iterates over provided storage keys and their respective proofs, + * using a Merkle proof to verify each storage value against the specified storage hash. + * @param storageHash The root hash of the storage trie for the account being verified. + * @param storageKeys An array of storage keys for which values need to be verified. + * @param proof A 2D array of Merkle proof elements for each storage key. + * @return bytes[] An array of storage values corresponding to each storage key. + */ + function _verifyStorageProof( + bytes32 storageHash, + bytes32[] memory storageKeys, + bytes[][] memory proof + ) private pure returns (bytes[] memory) { + bytes[] memory results = new bytes[](proof.length); + if (storageKeys.length == 0 || proof.length == 0 || storageKeys.length != proof.length) + revert InvalidStorageProofParams(); + for (uint256 i = 0; i < proof.length; ) { + RLPReader.RLPItem memory item = RLPReader.toRlpItem( + SecureMerkleTrie.get(abi.encode(storageKeys[i]), proof[i], storageHash) + ); + results[i] = item.toBytes(); + unchecked { + ++i; + } + } + return results; + } + + /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)). + uint256[49] private __gap; +} diff --git a/packages/evm/contracts/test/HashiProverTestUpgradeable.sol b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol new file mode 100644 index 00000000..d213f450 --- /dev/null +++ b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.20; + +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { HashiProverUpgradeable } from "../prover/HashiProverUpgradeable.sol"; + +contract HashiProverTestUpgradeable is UUPSUpgradeable, HashiProverUpgradeable { + function initialize(address shoyuBashi) public initializer { + __UUPSUpgradeable_init(); + __HashiProverUpgradeable_init(shoyuBashi); + } + + function getStorageValue( + HashiProverUpgradeable.AccountAndStorageProof calldata proof + ) external view returns (bytes[] memory) { + return verifyForeignStorage(proof); + } + + function getEventValues(HashiProverUpgradeable.ReceiptProof calldata proof) external view returns (bytes memory) { + return verifyForeignEvent(proof); + } + + function _authorizeUpgrade(address) internal override {} +} diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index f875ef45..e9116099 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -1,5 +1,6 @@ import "@nomicfoundation/hardhat-chai-matchers" import "@nomicfoundation/hardhat-toolbox" +import "@openzeppelin/hardhat-upgrades" import { config as dotenvConfig } from "dotenv" import "hardhat-change-network" import type { HardhatUserConfig } from "hardhat/config" diff --git a/packages/evm/package.json b/packages/evm/package.json index 5382aedf..0332d9c7 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -19,6 +19,7 @@ "@nomicfoundation/hardhat-verify": "^2.0.8", "@nomiclabs/hardhat-ethers": "^2.2.1", "@nomiclabs/hardhat-etherscan": "^3.1.2", + "@openzeppelin/hardhat-upgrades": "1.28.0", "@typechain/ethers-v5": "^10.1.1", "@typechain/hardhat": "^6.1.4", "@types/chai": "^4.3.4", diff --git a/packages/evm/test/05_HashiProver.spec.ts b/packages/evm/test/05_HashiProver.spec.ts index 575241c9..92f324c3 100644 --- a/packages/evm/test/05_HashiProver.spec.ts +++ b/packages/evm/test/05_HashiProver.spec.ts @@ -1,7 +1,7 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address" import { expect } from "chai" import { Contract } from "ethers" -import { ethers } from "hardhat" +import { ethers, upgrades } from "hardhat" import { ACCOUNT_AND_STORAGE_PROOF, @@ -12,13 +12,14 @@ import { const SOURCE_CHAIN_ID = 10 -let hashi: Contract, adapter: Contract, hashiProverTest: Contract, shoyuBashi: Contract, owner: SignerWithAddress +let hashi: Contract, adapter: Contract, shoyuBashi: Contract, hashiProvers: Contract[], owner: SignerWithAddress describe("HashiProver", () => { beforeEach(async () => { const Hashi = await ethers.getContractFactory("Hashi") const MockAdapter = await ethers.getContractFactory("MockAdapter") const HashiProverTest = await ethers.getContractFactory("HashiProverTest") + const HashiProverTestUpgradeable = await ethers.getContractFactory("HashiProverTestUpgradeable") const ShoyuBashi = await ethers.getContractFactory("ShoyuBashi") const signers = await ethers.getSigners() @@ -27,169 +28,193 @@ describe("HashiProver", () => { hashi = await Hashi.deploy() adapter = await MockAdapter.deploy() shoyuBashi = await ShoyuBashi.deploy(owner.address, hashi.address) - hashiProverTest = await HashiProverTest.deploy(shoyuBashi.address) + hashiProvers = [] + hashiProvers.push(await HashiProverTest.deploy(shoyuBashi.address)) + hashiProvers.push( + await upgrades.deployProxy(HashiProverTestUpgradeable, [shoyuBashi.address], { + kind: "uups", + }), + ) await shoyuBashi.enableAdapters(SOURCE_CHAIN_ID, [adapter.address], 1) }) it("should't be able to get the value if the block is not available", async () => { - await expect(hashiProverTest.getStorageValue(ACCOUNT_AND_STORAGE_PROOF)).to.be.revertedWithCustomError( - shoyuBashi, - "ThresholdNotMet", - ) + for (const hashiProver of hashiProvers) { + await expect(hashiProver.getStorageValue(ACCOUNT_AND_STORAGE_PROOF)).to.be.revertedWithCustomError( + shoyuBashi, + "ThresholdNotMet", + ) + } }) it("should't be able to get the value if the account proof is invalid", async () => { - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF] - wrongProof[6] = [ - "0xf90211a0ae94776f5c237b1e277aa2206301cfcfd3990fef08b60f1acbb7518bd2c353dda0a6dc453d3af2966ec75db38d8b592099cd823972058a68fdfa217788b8307544a04d85ebfc910e05b7de2b9a780dd871d984c36ab0f2c3f38eea8de6adfd1c444da0b5fea1bad6564cade5a31e978195248b2fd67bb195006827d1d61d0d72593f64a0460766bc32f1ce32df10f604758468b2998250732e91dcc43b3e8b185bda669ca0e21dcda48944f76f3d6508ab3d36035cdd82cf3d649f327e78532a62a40376b4a0dba8c95c72743ae2b7bad789e3038040f06f3afbca090b9da364ae39f0b15963a0bca1300f03dcef17a2f614fea6c34eb6a6f0c52f57e7fa15a75860541c671322a06ce72250e0d542a46b25347cada837c6316695108071861dd4b041f4bc56d0dea0f00addb60c5ee291719dfe5d93383380ce0c3a9cf54d27faa70fb3b30d424810a007fbe090c28df1099bc1768e0eefc350701227b351d4b0d434d81673b4867e0ca04e1032bc06c39c9d9ba823088d8ba3106c5018f4ef60765c72b1402c7a7cc5cea0a848e579a56b4c19e92b4a582288f1cf701ffcecfd439fb88c8f40173cabe43ea0d5839de991945ebd86629e32de1de57140de090842f3809bcf4a737bd75c13bea0287235eea51447d1b9b6686381830195568efc908c27092f561b2c65e4113ccda0d902b9642b74f04cf670d6d216c5f03d0d92f2e77c374e3e41c6c6265d8d429980", - "0xf90211a0d61d720b302bc422f0ece0f3c0e5172f16e8409b6b8bdd15db021284389b28fba0433f3f07bc576292134817472d7166183bc4730e837f964e3011b52bbf9b081aa02906d2af47eb17db297cac9e29381427fee7ebb53d6a914e402535f68c4c7c21a09de01bfc2a3986ed7a00b997b4cb7b55b837a155baa3bfc171efdf1ac31487c7a0e9357b5192820eea672e3194d2020b131f29abe5671c37601633c485358eb421a00a3f410ab91d016cb1716203d732962685a6fc9436862ab83d9fc5109346a041a096e1687da814500097774352c9f49064dac34fe0de9f1848190b5a56fbedcb17a07006adaa8c1b203eab5ee33ea19de791fc8c9cf5cb15ec90d1ef051c9e2ed78aa0468135eecd2271411b5c039c6dce226ee4b251d3e671fea0238347a522241313a045483167728fabead0fa82c604abcf05e0141b1e82d5e94a427b367839985ed4a04c53cd84dd5c5e90d3e4c6bf7583a2d71a5f440e78d2e550c618a9c326ebce64a0f120f7e462069e2b91d3ce0f1e9be2cef10b699399b76e188a710c74b8968432a05a912ef4d4b331e64a4f5ff4a6268ea3bd66c8b823fcb4c3bf7c6e200d302a1ca07aab0db239e967467ed9b3a155ef0a4e8d03d058d44e9e63c39312ad2a986fc8a0afe49319cf159e2916404743d4ef869043fdeb37c79b20fb355a98e8500491f1a024f8f3ea7890564e7c9b344f5493de5f87cfc5e4512c2396a51040cb64d6aba280", - "0xf90211a03b31c916b970491c86305379f7e67c97f98166cbc06fade873c5c7d324a7fa81a01b01b15dc4b7c66db50809b4236a98a2f05f156dc70a1e00ff7f009784a88173a098663d761acb23f77146aa5dc3fd4b487a3fec8d25ab2d5408e38e75489dea43a0a26e34fe93e7455b178fde2f89c1c99cfef61cbcb24bdb7ad8041be83ee67846a008662a0a8da5e79b6f4c601197a57ae00377f2f04a0f5edd17e3aed4c4d3777da0c3113823fec10487cde37f5ee2f39a8c72bd0413a21ba763acb5ebf0d40a49b6a044163b2ab486e7f99d831323ece00eb977db78a6594acb26082c5de00943616fa026fa7daf50745e3a6dfff87c28840cbb09ddac372d7759b796ea60b775f69f60a09c630785cd49c1b3aa3457999a1047d980392a18bc1d04f7763416ae01489ed6a07a1d5d86308774a7c26ed21faaa58d45efbb2616961a4bbe10d3fc88d99d0bf5a00c58bf78f9f278a3e75d22b39fda0df112a1cb8e05d79c32e5f31b94d4e99f64a070ed09023a65c88badb25edf59f2cab9708edc992ef461534b0e47ce3982ae90a01b690934defb8655cddc75185dd1612c1165ecfdcc8e7a19fdc57cae0f0065e8a054523f7b5547848216144e68b0ccdb1f819bd54ac210c2e4dd5a380edcce33f0a07dd9da455fb24559012c4903166f73f9c5e661b8c88f0bf7de019d73d4c19c89a04478f70fe968b2da1516a8f6b67a6b28011923c34ebecda2f45355e442cbcbbe80", - "0xf90211a0d5393c3c06c8d597f6f325789484f12da87d807df33096a0af3161e33c44b8b0a0f27d4b26d1822dc04180fe221b3e7cba86c9fc524791c951b6b71c242099ef3ba011d2b20160240582f75dc941e1785643f7652a43d1d62697808657b0a0b8e186a0e9acd52b94dd294c782ad25e727c17934726d62052deac6cd8ffab7cca3e4176a04dcd91b21b8c73a57023c649f7d27cb9443450ee8301f56d4693e667218fcb3ea0630078c69bd028cb16cfccc05feb9f960484ed470f7bc0d1acf25fea5a68de0ca09ee40510308e721235620dc519619981d81e8997c0e7ab5c91f32f1f9ddffdeca0176656e94e76511030173bc6a39fc6fc11078add4c391a6edceb34cc28b7c83fa01cc9e278e51e81a30d6b18410a7411287b95c03d9ec2fd23396f0ada6410d2a8a04060e9e3881260d3fff6981fdabe0861f12fe992e1a2704ff948339ab1ac694ca08b8a356d612925d089be937debbdcbe8a40a941bbd07d7fe168cdbe2bfdc2d7fa0ebad3b72886fc350a5aaa24d20d8a143754c92eabab4ee2cba59697e7771cd50a0c24cf965d70417de74ee02b9cfdde3138d434c2cbc0c21006c04cde27a2d9ab7a0f21f4798a55807d429caadba5da04b2d12fc43569e7bc6c4b965976f21643874a0ec71a00e5b53a2f6043ed744c66b7ae5bc6ea1c7d32066014723a7744ad0e446a08b985961a92fed93614049284d0f08665a7a9f1b5dfbb025682a9551f2660f5380", - "0xf90211a05510ce326198dee0033e6a2b29957f77687221d6f4b9a082f34922f9f589b003a0a6f336170753299b1adc48077e111e425fdc539ff7160a9babf8afdf5b5bef3ea0ad027c813622b3582247847a8537992e0a3f6a50e10c268d0ac8eacd1fd750bba037babb03742053f969204568854a958947fc93bcb978ebc85c83e35c5dc6fdfda07d3c1a847911e962071639472987bf9f0d112c983b393190af796342557a3ac5a07e243717881703400c60ec2fcc05040759a9646b61adb02412c8b0619e3059bda08acbc6de4a6c92f92dde22536a30bbc7bad7d44394e29312ebc9adfcd84ca300a0c558588e6ae83a42eaf44d7215f853262ad725faef6b3c73830e0903a31fefd6a0921f30e12a3b363b2aed7283870304a503f3613d311bae004eb7a922f6fd50f1a013987bb8a564c1513dd7b42682bb7237f51b94ac28780f41ae45a772e13fa76fa0596b2015a656fd4864bf6789cb5d4e4c67cc05114ae3fd7caa8355bd16cb00a7a0dea6e67052bdc0d975f894dbe6b4d7b7474c7bf6f2d0bb9b5298073a5e95a43ca0f532a3b3466a65f1e6e948bd1a9ac5b36bdb0f824609c37046acefb55f76d0b7a021462b95a644603890bea60588a71a17aac1e830fe290f6d9627f6a0ee173de7a0a5f42aa4c2fd149ba3a73028c450d1d3c0c10536bc1421c6e632bd56d63d7565a0156d9f2ce56dfe6e92fe5779b15821b6bae03882935a167a0d3c10e03523f77480", - "0xf90211a05d176d139f8def1c9dd83692adad161605fdec658eef8bc28afc4da848d97662a0e3d1f706ca6308d1f5e2d4cb6d641ba574b9ad852d6c878f9cec25ba7c8c8183a0f3647cf8efec130e89c09170b6a82a06cf2b9f4b15aff5d2e93d3c8cb5c294f8a071493e91397ece4c52482e3a20656b6780054a56986544555b07f5b053a4d722a0b60b270ab95f7787f4a40d6f68b667126fcb1272ddc0e9347205ebae3069b7d2a0b00e67c2e390212edde83ad1182fc5f373e9f47f11c8c69a04b87d75d0123b15a02f20f6d8f52b12c28ddba6fdca481dcb5a07363ff08758d83f041b2535666b18a0def25dabbdbebbdfef848073b51725528ae2680f9dc8b2371b52d97e5bce5645a0a27b621d4212470161d3a1786d70b24ba6f0ba013677c11e995feebb3f7be72aa0894ac9ee877ef9fc4ea797c33f994996567a17777a57d22050260b18bb994946a09bf44993469f668dadae80170dfb81156b0decb5f7fbceb62980a2508d3f3702a013fc551024f4961a8e4adedb726962975a60ae0553a65f0dd7e266b0ec34f2dca087561bc3f849b47500f1f503a264466616a31a4e7adf3f2b2753b3f8c60444bda0421bcca422a9f02867ab2b0269bad562e8d35bf35bb332a48d3be29b513e4a78a09fe8fdfd9c06692e93cc2f1b277aadebf462a38a28abfaaba33f4d7e4212ed71a0407f10b8182d07c7f9789d469b68926931e184d7afdc20322387db7dd8dd950b80", - "0xf9011180a0af3e6c1703878fa0f54ce9ef81044131303255beda112c1750bd46e46c17749780808080a0ee3ef4e754b7044fbaf982f80b8ab4ea00503fe3ec4c50fd7864e81ce1e6c4408080a075fb4f68ac224ec54d38eee3bd972654ca5ee1833530f0ebefd71a9f49cf09f1a05c099f09257a656d98101ccd60d3fbe861cb889f9699b8eed136268028021b70a0b90a5365f3205e9df1129eecaa73667c4d2c567f1ab45f63860c3671b46dc27780a0e38b7963499d1bbde43a95289356e98e19cdc1e21e10e097e1490f15e3662e0ba0ce536ccc69891fc11f58ebaa1a9f09bd1644af223c17493de3fa30e6e39f6845a052fe3bf973b9ff06f119a91481e15215c3eccadc584ce8b6e7a05ea68c73054180", - "0xf8669d3d676334b26bbb561def1bb646db346a0ea5f7c4f069e5ce4083818685b846f8440180a011a7fd82551848c90631f70de7f85bbc1fb9cce3618351c58eef7d86c6e6535da0aad43333d28e146557f1c682e8a4226743fb231fdd00a577512233bd9e921111", - ] - await expect(hashiProverTest.getStorageValue(wrongProof)).to.be.revertedWith("MerkleTrie: invalid root hash") + for (const hashiProver of hashiProvers) { + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF] + wrongProof[6] = [ + "0xf90211a0ae94776f5c237b1e277aa2206301cfcfd3990fef08b60f1acbb7518bd2c353dda0a6dc453d3af2966ec75db38d8b592099cd823972058a68fdfa217788b8307544a04d85ebfc910e05b7de2b9a780dd871d984c36ab0f2c3f38eea8de6adfd1c444da0b5fea1bad6564cade5a31e978195248b2fd67bb195006827d1d61d0d72593f64a0460766bc32f1ce32df10f604758468b2998250732e91dcc43b3e8b185bda669ca0e21dcda48944f76f3d6508ab3d36035cdd82cf3d649f327e78532a62a40376b4a0dba8c95c72743ae2b7bad789e3038040f06f3afbca090b9da364ae39f0b15963a0bca1300f03dcef17a2f614fea6c34eb6a6f0c52f57e7fa15a75860541c671322a06ce72250e0d542a46b25347cada837c6316695108071861dd4b041f4bc56d0dea0f00addb60c5ee291719dfe5d93383380ce0c3a9cf54d27faa70fb3b30d424810a007fbe090c28df1099bc1768e0eefc350701227b351d4b0d434d81673b4867e0ca04e1032bc06c39c9d9ba823088d8ba3106c5018f4ef60765c72b1402c7a7cc5cea0a848e579a56b4c19e92b4a582288f1cf701ffcecfd439fb88c8f40173cabe43ea0d5839de991945ebd86629e32de1de57140de090842f3809bcf4a737bd75c13bea0287235eea51447d1b9b6686381830195568efc908c27092f561b2c65e4113ccda0d902b9642b74f04cf670d6d216c5f03d0d92f2e77c374e3e41c6c6265d8d429980", + "0xf90211a0d61d720b302bc422f0ece0f3c0e5172f16e8409b6b8bdd15db021284389b28fba0433f3f07bc576292134817472d7166183bc4730e837f964e3011b52bbf9b081aa02906d2af47eb17db297cac9e29381427fee7ebb53d6a914e402535f68c4c7c21a09de01bfc2a3986ed7a00b997b4cb7b55b837a155baa3bfc171efdf1ac31487c7a0e9357b5192820eea672e3194d2020b131f29abe5671c37601633c485358eb421a00a3f410ab91d016cb1716203d732962685a6fc9436862ab83d9fc5109346a041a096e1687da814500097774352c9f49064dac34fe0de9f1848190b5a56fbedcb17a07006adaa8c1b203eab5ee33ea19de791fc8c9cf5cb15ec90d1ef051c9e2ed78aa0468135eecd2271411b5c039c6dce226ee4b251d3e671fea0238347a522241313a045483167728fabead0fa82c604abcf05e0141b1e82d5e94a427b367839985ed4a04c53cd84dd5c5e90d3e4c6bf7583a2d71a5f440e78d2e550c618a9c326ebce64a0f120f7e462069e2b91d3ce0f1e9be2cef10b699399b76e188a710c74b8968432a05a912ef4d4b331e64a4f5ff4a6268ea3bd66c8b823fcb4c3bf7c6e200d302a1ca07aab0db239e967467ed9b3a155ef0a4e8d03d058d44e9e63c39312ad2a986fc8a0afe49319cf159e2916404743d4ef869043fdeb37c79b20fb355a98e8500491f1a024f8f3ea7890564e7c9b344f5493de5f87cfc5e4512c2396a51040cb64d6aba280", + "0xf90211a03b31c916b970491c86305379f7e67c97f98166cbc06fade873c5c7d324a7fa81a01b01b15dc4b7c66db50809b4236a98a2f05f156dc70a1e00ff7f009784a88173a098663d761acb23f77146aa5dc3fd4b487a3fec8d25ab2d5408e38e75489dea43a0a26e34fe93e7455b178fde2f89c1c99cfef61cbcb24bdb7ad8041be83ee67846a008662a0a8da5e79b6f4c601197a57ae00377f2f04a0f5edd17e3aed4c4d3777da0c3113823fec10487cde37f5ee2f39a8c72bd0413a21ba763acb5ebf0d40a49b6a044163b2ab486e7f99d831323ece00eb977db78a6594acb26082c5de00943616fa026fa7daf50745e3a6dfff87c28840cbb09ddac372d7759b796ea60b775f69f60a09c630785cd49c1b3aa3457999a1047d980392a18bc1d04f7763416ae01489ed6a07a1d5d86308774a7c26ed21faaa58d45efbb2616961a4bbe10d3fc88d99d0bf5a00c58bf78f9f278a3e75d22b39fda0df112a1cb8e05d79c32e5f31b94d4e99f64a070ed09023a65c88badb25edf59f2cab9708edc992ef461534b0e47ce3982ae90a01b690934defb8655cddc75185dd1612c1165ecfdcc8e7a19fdc57cae0f0065e8a054523f7b5547848216144e68b0ccdb1f819bd54ac210c2e4dd5a380edcce33f0a07dd9da455fb24559012c4903166f73f9c5e661b8c88f0bf7de019d73d4c19c89a04478f70fe968b2da1516a8f6b67a6b28011923c34ebecda2f45355e442cbcbbe80", + "0xf90211a0d5393c3c06c8d597f6f325789484f12da87d807df33096a0af3161e33c44b8b0a0f27d4b26d1822dc04180fe221b3e7cba86c9fc524791c951b6b71c242099ef3ba011d2b20160240582f75dc941e1785643f7652a43d1d62697808657b0a0b8e186a0e9acd52b94dd294c782ad25e727c17934726d62052deac6cd8ffab7cca3e4176a04dcd91b21b8c73a57023c649f7d27cb9443450ee8301f56d4693e667218fcb3ea0630078c69bd028cb16cfccc05feb9f960484ed470f7bc0d1acf25fea5a68de0ca09ee40510308e721235620dc519619981d81e8997c0e7ab5c91f32f1f9ddffdeca0176656e94e76511030173bc6a39fc6fc11078add4c391a6edceb34cc28b7c83fa01cc9e278e51e81a30d6b18410a7411287b95c03d9ec2fd23396f0ada6410d2a8a04060e9e3881260d3fff6981fdabe0861f12fe992e1a2704ff948339ab1ac694ca08b8a356d612925d089be937debbdcbe8a40a941bbd07d7fe168cdbe2bfdc2d7fa0ebad3b72886fc350a5aaa24d20d8a143754c92eabab4ee2cba59697e7771cd50a0c24cf965d70417de74ee02b9cfdde3138d434c2cbc0c21006c04cde27a2d9ab7a0f21f4798a55807d429caadba5da04b2d12fc43569e7bc6c4b965976f21643874a0ec71a00e5b53a2f6043ed744c66b7ae5bc6ea1c7d32066014723a7744ad0e446a08b985961a92fed93614049284d0f08665a7a9f1b5dfbb025682a9551f2660f5380", + "0xf90211a05510ce326198dee0033e6a2b29957f77687221d6f4b9a082f34922f9f589b003a0a6f336170753299b1adc48077e111e425fdc539ff7160a9babf8afdf5b5bef3ea0ad027c813622b3582247847a8537992e0a3f6a50e10c268d0ac8eacd1fd750bba037babb03742053f969204568854a958947fc93bcb978ebc85c83e35c5dc6fdfda07d3c1a847911e962071639472987bf9f0d112c983b393190af796342557a3ac5a07e243717881703400c60ec2fcc05040759a9646b61adb02412c8b0619e3059bda08acbc6de4a6c92f92dde22536a30bbc7bad7d44394e29312ebc9adfcd84ca300a0c558588e6ae83a42eaf44d7215f853262ad725faef6b3c73830e0903a31fefd6a0921f30e12a3b363b2aed7283870304a503f3613d311bae004eb7a922f6fd50f1a013987bb8a564c1513dd7b42682bb7237f51b94ac28780f41ae45a772e13fa76fa0596b2015a656fd4864bf6789cb5d4e4c67cc05114ae3fd7caa8355bd16cb00a7a0dea6e67052bdc0d975f894dbe6b4d7b7474c7bf6f2d0bb9b5298073a5e95a43ca0f532a3b3466a65f1e6e948bd1a9ac5b36bdb0f824609c37046acefb55f76d0b7a021462b95a644603890bea60588a71a17aac1e830fe290f6d9627f6a0ee173de7a0a5f42aa4c2fd149ba3a73028c450d1d3c0c10536bc1421c6e632bd56d63d7565a0156d9f2ce56dfe6e92fe5779b15821b6bae03882935a167a0d3c10e03523f77480", + "0xf90211a05d176d139f8def1c9dd83692adad161605fdec658eef8bc28afc4da848d97662a0e3d1f706ca6308d1f5e2d4cb6d641ba574b9ad852d6c878f9cec25ba7c8c8183a0f3647cf8efec130e89c09170b6a82a06cf2b9f4b15aff5d2e93d3c8cb5c294f8a071493e91397ece4c52482e3a20656b6780054a56986544555b07f5b053a4d722a0b60b270ab95f7787f4a40d6f68b667126fcb1272ddc0e9347205ebae3069b7d2a0b00e67c2e390212edde83ad1182fc5f373e9f47f11c8c69a04b87d75d0123b15a02f20f6d8f52b12c28ddba6fdca481dcb5a07363ff08758d83f041b2535666b18a0def25dabbdbebbdfef848073b51725528ae2680f9dc8b2371b52d97e5bce5645a0a27b621d4212470161d3a1786d70b24ba6f0ba013677c11e995feebb3f7be72aa0894ac9ee877ef9fc4ea797c33f994996567a17777a57d22050260b18bb994946a09bf44993469f668dadae80170dfb81156b0decb5f7fbceb62980a2508d3f3702a013fc551024f4961a8e4adedb726962975a60ae0553a65f0dd7e266b0ec34f2dca087561bc3f849b47500f1f503a264466616a31a4e7adf3f2b2753b3f8c60444bda0421bcca422a9f02867ab2b0269bad562e8d35bf35bb332a48d3be29b513e4a78a09fe8fdfd9c06692e93cc2f1b277aadebf462a38a28abfaaba33f4d7e4212ed71a0407f10b8182d07c7f9789d469b68926931e184d7afdc20322387db7dd8dd950b80", + "0xf9011180a0af3e6c1703878fa0f54ce9ef81044131303255beda112c1750bd46e46c17749780808080a0ee3ef4e754b7044fbaf982f80b8ab4ea00503fe3ec4c50fd7864e81ce1e6c4408080a075fb4f68ac224ec54d38eee3bd972654ca5ee1833530f0ebefd71a9f49cf09f1a05c099f09257a656d98101ccd60d3fbe861cb889f9699b8eed136268028021b70a0b90a5365f3205e9df1129eecaa73667c4d2c567f1ab45f63860c3671b46dc27780a0e38b7963499d1bbde43a95289356e98e19cdc1e21e10e097e1490f15e3662e0ba0ce536ccc69891fc11f58ebaa1a9f09bd1644af223c17493de3fa30e6e39f6845a052fe3bf973b9ff06f119a91481e15215c3eccadc584ce8b6e7a05ea68c73054180", + "0xf8669d3d676334b26bbb561def1bb646db346a0ea5f7c4f069e5ce4083818685b846f8440180a011a7fd82551848c90631f70de7f85bbc1fb9cce3618351c58eef7d86c6e6535da0aad43333d28e146557f1c682e8a4226743fb231fdd00a577512233bd9e921111", + ] + await expect(hashiProver.getStorageValue(wrongProof)).to.be.revertedWith("MerkleTrie: invalid root hash") + } }) it("should't be able to get the value if the storage proof is invalid", async () => { - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF] - wrongProof[9] = [ - [ - "0xf90211a01922b5f82f07bee421217744ed6d4e95b98852241f24dffa2f5701b1ddb8e6dca03fec17456b28fe0aea41291618b766813d90061104d8731e6e937b0922cae1f6a0fb94b76b2f2c5d4b40890a18b9f0579966eb56274035a58010db113ccbab922fa085b2e52483d7a1448504098bd8b3a0fc68becfe6fcf5e8f7442d08d1c17d9446a0c8b2aa37759feac9aad765fca7545ab9d02015364261d3f35384154e77ef77e9a0bc48fb8581b0926eb1d707cb1668b5ecdf2b1759fb7ed8d440bf1163103bd810a046fe65e822efc9f1b49e43ed4eb7600e9658c306b70a95999aeb0112c9954f9ca03d66c408b9ced8ee40c6281f15e26bb7db314045d5f65322fc1d5e24544b9192a0b26bf58b679aaf2a0a5f5a7fc9507e856f31e01a7ea47d9c5719957e51d99f92a003555409bff0cbb217e5d9fbd7d9e3b46a451e2b3cc0f27b34a3b553634770f7a05f71f83b940082edb3f0afaedd000ae4789a8b459c0befecf0085308961a38f4a0110aca3b49ff8a7fc3d60295d0c18602e576427a02907986d3fcdec5c8406607a0b197a531e48bf6f203d6f8b4088117caaa55d2318177d00a849c9bb9c0be11b5a021c55c465168ceb84725b61988c7c174880c9bccb99510ebffcf715f01344022a0173421253267ac8dacdd78bb3a49e4e68ce44c987335e7e22e2067f5998ccc8ba0ddb9469be4af0c764ae2984533a34b6ac6ad4535a7bf773d1bdcaba414288d4e80", - "0xf90211a0134f748fc5e8562c4037bb335c253e159c2d3c7a1dc48b1e006fee1ffcc63874a0dcad9ec65f0b0b3e3d265b468ceda4c2626bea957ba6dd0f25e91d8f43615dcba0b8fdad766b78548db43d60da964d1abdd784ae56bd9ad9dd5ce7911beadab941a01db88587d7758f452204d265122d451f416f29219de91d8f1fd98b4695ad56f8a06464403607b9759cf6cb0e1bdd58d3a231ece185267c59d0113836bbce312007a0a23247953c05226318750e90668afd8b8f4a308f1f3e5573f92c03cd4fa9cc99a0ec186ad6ea36e64969fac78982f9ddd2c78f01fb5f059afc8d9253cafb348272a00e259709d156973caac69a52dbde1569f0ea9fc58cc9333b6fff01bed4ced9c3a01f76d216b1d1f75ebdcece38a62dc6d85cf090cec0b17ea8fe4a2fbadf02e418a0a44e06aa48e8e2b81b82ac7a55d10e0e75fb0016475f40b4b2b199016fefef11a04e31f7d98493c4af332a55a088d75bd53a55d37feee0fb4ea4bb89bd6cf1189da01fe39db746e4eef3572d1863d2edf73ef178986a33929a353e30d5a5459cffb7a0c64a8a52d3dfb4c33e5eac53820c25604e4c8f34062e2f31a00ada4c4e8ac794a02b09776c323c5f8fc6b69732fc17e7ac78fb63c9a42243b5b65bb067b05af034a0c371630f7af67645f11a19b70a01e20284fd2c3afa8ad5e72fa939e775090b94a0a2680edf63d1735ee9ce81c2bb867aa6708db5be648b511b2997cf6a82b7b12a80", - "0xf90211a046660614c4b352e38c7a40b3fbacf123b88d343407c60aa3df2fc14e5c57667ea0f326e8d140b8c178ef04d4af3f9435159ad3c3cc9029a24daced2a2e5a7edadba04beaf51b9e686b2e9a3cb11906ac2c2b975a1f2b21fae6345baa832716d08904a00d9c648844e04c5a20d669382e429a02691b92a9ed51346e9e6b4c3e11950c51a0116e5123177580be67dfd0beaa66ff0aaad0d390afa05246c44dc8de9736c21ea0c566c23ca1b65aec125de0d781343787ae3f1037793af3d12e976ebc26b25d82a0ecc286af188cbb0d2f91980a6547e9c21d31e436f362565998d38063cb8e4a43a0161332b061fd1ae44a9cc9a7ee560b1f416a75f723df1d4607487149f0a6ef98a0ce4de6144c942d8cb5180aad406ac42934f039bafe6a7b1fba6094b104e3ed01a088da9aca558d0c51ce0fb208ab108b143e0a5122bcd5bd85c35e09b39a67a7ada0b24c5e971bdcc7151c89d69c0046c899379fcb9fd479d2b8a05df7348f08e4bda0bdb15b37b990be1e658ede5ed0e556d73fca185489124cad494721bd0c9dc79da0279294696fab46dcb10b5069d1929b96500342e6609fc85b5c242ebfd6dee280a02b3df2dfda83841f27315d0dcd3025dce8ee53425de4ccea153dd8f9893b65d6a07b3b6cb9b2148a7086adc24501672da8b0fc348a1fa78051ebb603f337f68de8a025f98ef38ab7bbaf176f7284ff1548b7638d013f817fd84979061507c4cb3f8080", - "0xf90211a0817f0522b611763caedae0abdbf8a7d1fc523cc759bc6dd400d8837d94587832a0ecd37fcea2b496aeb18f74786fc7aeda2ea78bfb55cf27a829b69c4d15e2525ca019a27a34379a6a5dcd5a1cb8fdc5b7351b40eeb3f4e7d09db2daaf688e7a11b8a02339835ad35c836c7c9b1fd17f8ef9aa377a9e458316252ac63efe702fd895bda08e96214ae9077f46f6d2a440af91126a5bf62732edd0dc513efadba4b956fe9ea026370016e564a879e26f01a077e73badcca1551a92a05571e86d07af2a049493a0fab6a8b576dbf710ba642f849c36ab54ed462ac0f8e3593ad6d25af4e6f23677a06ed7fc714f359a29a6bd13c1a804fc6a19938f46c377fc97e787706dc8da0e58a0c0d3305cf25baab40da08bb2c141d0984d60afc353c4d0e708fed92fb2239460a057cdd07f66b3a31f01079d3933ee6a4fd5280ba7abec7c9bc1404ccca5224d9aa0ab9e1abf9a0bfd89d1483448ec555a10d7956b434787ae6c55605ce4c3fbb3e5a0d9d5c4782ba8bceaf3887b440321190898df7ce785679dcc628516de02069a17a05565679c56603a5614f90447648485ba6f3e324df4845af69482209fcc620156a09e4205f6a5c8e633cb7e5048148675d7aef4030de17d81e6d8e5a3e5f5b77a8ba0b995d98c91905fa0e083455afe9d4219e4f040c6e3bdf948b139a8d12b192157a05ed2de5e483fa16f32c9d56979082e36c77c1102e12020136172dfed9c85d28880", - "0xf90131a0d56f8e12a9254f3fab9b7c5cb9e917dbc2540b1fa8e14f22840257d30c47adbfa0bcf412e2dcc182720eb7a6d3b260488603cefcdc206815beeea0b4700adb9e46808080a0ba844e9671269f0a8ab47cd42fc59e9ff5077adfa3c400e243146fcb708f4e5da0d1e9012aff863e29b5c2b7111ed41b55669bc3bd70aafd9302247c9a71176550a03f9b33fa55d938ae9dd41dfed6b17fc52327d20a2503c8e5d85a2f401a0e6ea380a0d4947649b148740ce5687696c87bb07217543329c73f7bb8900f1140b1563f3ca0c41116acc085e1d1b88f0998eacf59cc10a4646e9ffc4428b221c00ec5b1f4cca08c6b7c02a459200f13e8b385d3dcb998ec8f9c03cc1b7c8b3a5e753d5a65364880a09dc8cbc03d181ee816de24c1baeaa398a7b98e5f33e730011505e8496e74fefd808080", - "0xe79e37a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db98786b56d157e7f5b", - ], - ] - await expect(hashiProverTest.getStorageValue(wrongProof)).to.be.revertedWith( - "MerkleTrie: invalid large internal hash", - ) + for (const hashiProver of hashiProvers) { + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF] + wrongProof[9] = [ + [ + "0xf90211a01922b5f82f07bee421217744ed6d4e95b98852241f24dffa2f5701b1ddb8e6dca03fec17456b28fe0aea41291618b766813d90061104d8731e6e937b0922cae1f6a0fb94b76b2f2c5d4b40890a18b9f0579966eb56274035a58010db113ccbab922fa085b2e52483d7a1448504098bd8b3a0fc68becfe6fcf5e8f7442d08d1c17d9446a0c8b2aa37759feac9aad765fca7545ab9d02015364261d3f35384154e77ef77e9a0bc48fb8581b0926eb1d707cb1668b5ecdf2b1759fb7ed8d440bf1163103bd810a046fe65e822efc9f1b49e43ed4eb7600e9658c306b70a95999aeb0112c9954f9ca03d66c408b9ced8ee40c6281f15e26bb7db314045d5f65322fc1d5e24544b9192a0b26bf58b679aaf2a0a5f5a7fc9507e856f31e01a7ea47d9c5719957e51d99f92a003555409bff0cbb217e5d9fbd7d9e3b46a451e2b3cc0f27b34a3b553634770f7a05f71f83b940082edb3f0afaedd000ae4789a8b459c0befecf0085308961a38f4a0110aca3b49ff8a7fc3d60295d0c18602e576427a02907986d3fcdec5c8406607a0b197a531e48bf6f203d6f8b4088117caaa55d2318177d00a849c9bb9c0be11b5a021c55c465168ceb84725b61988c7c174880c9bccb99510ebffcf715f01344022a0173421253267ac8dacdd78bb3a49e4e68ce44c987335e7e22e2067f5998ccc8ba0ddb9469be4af0c764ae2984533a34b6ac6ad4535a7bf773d1bdcaba414288d4e80", + "0xf90211a0134f748fc5e8562c4037bb335c253e159c2d3c7a1dc48b1e006fee1ffcc63874a0dcad9ec65f0b0b3e3d265b468ceda4c2626bea957ba6dd0f25e91d8f43615dcba0b8fdad766b78548db43d60da964d1abdd784ae56bd9ad9dd5ce7911beadab941a01db88587d7758f452204d265122d451f416f29219de91d8f1fd98b4695ad56f8a06464403607b9759cf6cb0e1bdd58d3a231ece185267c59d0113836bbce312007a0a23247953c05226318750e90668afd8b8f4a308f1f3e5573f92c03cd4fa9cc99a0ec186ad6ea36e64969fac78982f9ddd2c78f01fb5f059afc8d9253cafb348272a00e259709d156973caac69a52dbde1569f0ea9fc58cc9333b6fff01bed4ced9c3a01f76d216b1d1f75ebdcece38a62dc6d85cf090cec0b17ea8fe4a2fbadf02e418a0a44e06aa48e8e2b81b82ac7a55d10e0e75fb0016475f40b4b2b199016fefef11a04e31f7d98493c4af332a55a088d75bd53a55d37feee0fb4ea4bb89bd6cf1189da01fe39db746e4eef3572d1863d2edf73ef178986a33929a353e30d5a5459cffb7a0c64a8a52d3dfb4c33e5eac53820c25604e4c8f34062e2f31a00ada4c4e8ac794a02b09776c323c5f8fc6b69732fc17e7ac78fb63c9a42243b5b65bb067b05af034a0c371630f7af67645f11a19b70a01e20284fd2c3afa8ad5e72fa939e775090b94a0a2680edf63d1735ee9ce81c2bb867aa6708db5be648b511b2997cf6a82b7b12a80", + "0xf90211a046660614c4b352e38c7a40b3fbacf123b88d343407c60aa3df2fc14e5c57667ea0f326e8d140b8c178ef04d4af3f9435159ad3c3cc9029a24daced2a2e5a7edadba04beaf51b9e686b2e9a3cb11906ac2c2b975a1f2b21fae6345baa832716d08904a00d9c648844e04c5a20d669382e429a02691b92a9ed51346e9e6b4c3e11950c51a0116e5123177580be67dfd0beaa66ff0aaad0d390afa05246c44dc8de9736c21ea0c566c23ca1b65aec125de0d781343787ae3f1037793af3d12e976ebc26b25d82a0ecc286af188cbb0d2f91980a6547e9c21d31e436f362565998d38063cb8e4a43a0161332b061fd1ae44a9cc9a7ee560b1f416a75f723df1d4607487149f0a6ef98a0ce4de6144c942d8cb5180aad406ac42934f039bafe6a7b1fba6094b104e3ed01a088da9aca558d0c51ce0fb208ab108b143e0a5122bcd5bd85c35e09b39a67a7ada0b24c5e971bdcc7151c89d69c0046c899379fcb9fd479d2b8a05df7348f08e4bda0bdb15b37b990be1e658ede5ed0e556d73fca185489124cad494721bd0c9dc79da0279294696fab46dcb10b5069d1929b96500342e6609fc85b5c242ebfd6dee280a02b3df2dfda83841f27315d0dcd3025dce8ee53425de4ccea153dd8f9893b65d6a07b3b6cb9b2148a7086adc24501672da8b0fc348a1fa78051ebb603f337f68de8a025f98ef38ab7bbaf176f7284ff1548b7638d013f817fd84979061507c4cb3f8080", + "0xf90211a0817f0522b611763caedae0abdbf8a7d1fc523cc759bc6dd400d8837d94587832a0ecd37fcea2b496aeb18f74786fc7aeda2ea78bfb55cf27a829b69c4d15e2525ca019a27a34379a6a5dcd5a1cb8fdc5b7351b40eeb3f4e7d09db2daaf688e7a11b8a02339835ad35c836c7c9b1fd17f8ef9aa377a9e458316252ac63efe702fd895bda08e96214ae9077f46f6d2a440af91126a5bf62732edd0dc513efadba4b956fe9ea026370016e564a879e26f01a077e73badcca1551a92a05571e86d07af2a049493a0fab6a8b576dbf710ba642f849c36ab54ed462ac0f8e3593ad6d25af4e6f23677a06ed7fc714f359a29a6bd13c1a804fc6a19938f46c377fc97e787706dc8da0e58a0c0d3305cf25baab40da08bb2c141d0984d60afc353c4d0e708fed92fb2239460a057cdd07f66b3a31f01079d3933ee6a4fd5280ba7abec7c9bc1404ccca5224d9aa0ab9e1abf9a0bfd89d1483448ec555a10d7956b434787ae6c55605ce4c3fbb3e5a0d9d5c4782ba8bceaf3887b440321190898df7ce785679dcc628516de02069a17a05565679c56603a5614f90447648485ba6f3e324df4845af69482209fcc620156a09e4205f6a5c8e633cb7e5048148675d7aef4030de17d81e6d8e5a3e5f5b77a8ba0b995d98c91905fa0e083455afe9d4219e4f040c6e3bdf948b139a8d12b192157a05ed2de5e483fa16f32c9d56979082e36c77c1102e12020136172dfed9c85d28880", + "0xf90131a0d56f8e12a9254f3fab9b7c5cb9e917dbc2540b1fa8e14f22840257d30c47adbfa0bcf412e2dcc182720eb7a6d3b260488603cefcdc206815beeea0b4700adb9e46808080a0ba844e9671269f0a8ab47cd42fc59e9ff5077adfa3c400e243146fcb708f4e5da0d1e9012aff863e29b5c2b7111ed41b55669bc3bd70aafd9302247c9a71176550a03f9b33fa55d938ae9dd41dfed6b17fc52327d20a2503c8e5d85a2f401a0e6ea380a0d4947649b148740ce5687696c87bb07217543329c73f7bb8900f1140b1563f3ca0c41116acc085e1d1b88f0998eacf59cc10a4646e9ffc4428b221c00ec5b1f4cca08c6b7c02a459200f13e8b385d3dcb998ec8f9c03cc1b7c8b3a5e753d5a65364880a09dc8cbc03d181ee816de24c1baeaa398a7b98e5f33e730011505e8496e74fefd808080", + "0xe79e37a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db98786b56d157e7f5b", + ], + ] + await expect(hashiProver.getStorageValue(wrongProof)).to.be.revertedWith( + "MerkleTrie: invalid large internal hash", + ) + } }) it("should be able to get the value when account and storage proof is valid", async () => { - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - expect(await hashiProverTest.getStorageValue(ACCOUNT_AND_STORAGE_PROOF)).to.be.deep.eq(["0xb56d157e7f5a"]) + for (const hashiProver of hashiProvers) { + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + expect(await hashiProver.getStorageValue(ACCOUNT_AND_STORAGE_PROOF)).to.be.deep.eq(["0xb56d157e7f5a"]) + } }) it("should be able to get the value using ancestral blocks", async () => { - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - expect(await hashiProverTest.getStorageValue(ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS)).to.be.deep.eq([ - "0xb56d157e7f5a", - ]) + for (const hashiProver of hashiProvers) { + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + expect(await hashiProver.getStorageValue(ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS)).to.be.deep.eq([ + "0xb56d157e7f5a", + ]) + } }) it("should be able to get the value using even you submit a valid chain of ancestral blocks and and the selected one is in the middle of the chain", async () => { - const correctProof = [...ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS] - correctProof[4] = [ - "0xf90244a006f019ce5f815a48534f1894e0bf2bc479f3624eb3658a5b8b09683210371cffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0db07d5c7f51b0fabc0ab6abffb98efcac1cb95f63dcae01ea8e73301558f1c94a05ab78472371830bfed304d360240d57e7bee41309297278fd0dcd5b198979a2ea0a9bcb4d6a8f248c15860a40a38c1d965a5c33173226d35eab3cfbb7112bd3532b9010040703482510e004000001884022000202001880a000450400806000144d2210045081100280910224008001040003110004402640012220006200001402020c1000084188008208a3010880940b82000149414030182049548200000208c0001190000281a5406000010100203040900e0311685481c0150002500124808000840000003088c028200010600104840049080d5c08aa14000111090084a2800001210002815123401000011028040260008840010a000000040810410880004804000002308064400c10028860002800840c480040582c3008020040820102901001028010094000110102801088001119000100401828100840080000021280680840783ee938401c9c38083574af28466fbb6df80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301fa63a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", - "0xf90244a0bdb13612402a6004f26314e340d25c864e27cbd26d90464c3a3191195698a038a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a016cd64cf4911d99e5413d5740b90cade7def9698cdabf726e8d931bd5967f878a0c622bc1d9430ec4062302efe23cc8127742f8ca8978a7c3b27743124c4b7430ca093be9a83ad2bf4a046bab6c7a9bf877f261238a9b96058936458d61c2ee4587eb90100907030825b420001a40218a688204060400c00280164a0000844000344c42900250810046000040a80400090006023000150144000032208045046c0406642c12a140080000c308a2100a02952a5302110c45008014b201619000101280200039daa43088b44000010115000020008318003460a4008160000000012a80a55184024002300822500582132023801b0041122168080200268002400582a388019821040923023048002811120890846001a8428862081420980800010200028406000120220420008354800060262301028f12000808803168008001aa801201003100c8d20b3002209904049028801c20800010414809a00800088042013101080840783ee928401c9c38083771a9b8466fbb6dd80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f941a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", - "0xf90244a02abeb2f843b0c7e14af20d88b51580260281529864bac81386715d186b188feca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a07f973efd45c15188ca5b64afe8f2a431fc49da885ce3473aca30f18230bd9567a0070547bf249b370121ae7bfcf64c421a91c25b4a694b1982b1f473138d69bb22a057b9a7532db0ead6850099e396471c6ab4b1c1970850d259abe2e1e8f4003d51b90100c401a002c0040080d10018404420012080006908000402002006880044e0011025081804301200210000a0100010380010c1021000122280a4010140406809c822c00088b0290808200008b948a10401148608004108100414000000902800011485010882042204128012a00110480100210002ea0900400b010110010910080800006508800151002142001a08002050001781a82110008000109a2a0885180200000658028e000001010409089600268470040042008020900052a85800806910100200020800130088060882000042c40010038002008100000840046040583cc00902840010209040a1000055011001342c408089400620a08000142c0080840783ee918401c9c3808371781a8466fbb6db80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f846a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", - "0xf90244a012dfd2e2be4bcdd6b79eac25fb75a3fc4d755aa463acfc7ff80f3bf4ec49353aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0e49a1cb205090a958479f62241d3c812164630f09859538b98f20929700832caa0fb422fe08fca21bf0de2f413bee27c3ff3436ea54e32587238ce182d6dc1fb19a0274c2dbc71d835379c18401e3268e7c4f009b670b9a0ddca04743b7b0b65a111b90100005030021000000300001880204000001200020c000020000840000042c009000d08100030000108004000000000210800100442000022082040004040600000000280008008308a4000002850000000008400a02008000000210000000000000000010006040000000011000000889080004000200a00808000001208480908002000010002300060000202010180200100500080000000020000000a1004018a00001001000080300108208000000000000000000000090080408300000040400001020004240028008006004200000805800002880300000000084800200000300009002000000800001000000100000a011010902a00800010040001000080840783ee908401c9c3808335bb028466fbb6d980a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f8dea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", - "0xf90244a0186b3f6370955f23ec37702b09582d6425ddfda544cb413ac327ef7f572f5b56a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0a6c0e65d726f0bfd262c65adafef031343d8950aed130b5fcfe27b1bef2212d5a0183a4a9f9dd4440ab81732a15891f6fd598f676df500c46a5dfcc24bb3278fc9a0440271bf3661f283439affb6cc2c3bc7903450f33ef3fa59a0205b3de7c73c65b90100881021024102000000000080002000002880012a000181080004000044c0010005081124212000a0002016900241201000000040810322840400080050600000008c8000000800080100600900a00000008001000308080001402040000044048008010026048248000090000000386204210000006808408010011000882008000000010080002000900a20000120201020148280200040040400004a4020008201c00052020400000021008008040018000000200400000090001080000400c400000200000000210000062042020820400004808022008400004840002010003000412020400009040002022001000000000001800000828008800001000080840783ee8f8401c9c380833f80448466fbb6d780a09996ce9a05bb1040afb647edc64c2c757853aacebbac768bbb021593fb1e501d8800000000000000008301f934a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a061fe46939ae209665c1dd0107123cd3e34c67ae2e0f21ef5adda87929dedc8eb", - ] - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - expect(await hashiProverTest.getStorageValue(correctProof)).to.be.deep.eq(["0xb56d157e7f5a"]) + for (const hashiProver of hashiProvers) { + const correctProof = [...ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS] + correctProof[4] = [ + "0xf90244a006f019ce5f815a48534f1894e0bf2bc479f3624eb3658a5b8b09683210371cffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0db07d5c7f51b0fabc0ab6abffb98efcac1cb95f63dcae01ea8e73301558f1c94a05ab78472371830bfed304d360240d57e7bee41309297278fd0dcd5b198979a2ea0a9bcb4d6a8f248c15860a40a38c1d965a5c33173226d35eab3cfbb7112bd3532b9010040703482510e004000001884022000202001880a000450400806000144d2210045081100280910224008001040003110004402640012220006200001402020c1000084188008208a3010880940b82000149414030182049548200000208c0001190000281a5406000010100203040900e0311685481c0150002500124808000840000003088c028200010600104840049080d5c08aa14000111090084a2800001210002815123401000011028040260008840010a000000040810410880004804000002308064400c10028860002800840c480040582c3008020040820102901001028010094000110102801088001119000100401828100840080000021280680840783ee938401c9c38083574af28466fbb6df80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301fa63a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", + "0xf90244a0bdb13612402a6004f26314e340d25c864e27cbd26d90464c3a3191195698a038a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a016cd64cf4911d99e5413d5740b90cade7def9698cdabf726e8d931bd5967f878a0c622bc1d9430ec4062302efe23cc8127742f8ca8978a7c3b27743124c4b7430ca093be9a83ad2bf4a046bab6c7a9bf877f261238a9b96058936458d61c2ee4587eb90100907030825b420001a40218a688204060400c00280164a0000844000344c42900250810046000040a80400090006023000150144000032208045046c0406642c12a140080000c308a2100a02952a5302110c45008014b201619000101280200039daa43088b44000010115000020008318003460a4008160000000012a80a55184024002300822500582132023801b0041122168080200268002400582a388019821040923023048002811120890846001a8428862081420980800010200028406000120220420008354800060262301028f12000808803168008001aa801201003100c8d20b3002209904049028801c20800010414809a00800088042013101080840783ee928401c9c38083771a9b8466fbb6dd80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f941a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", + "0xf90244a02abeb2f843b0c7e14af20d88b51580260281529864bac81386715d186b188feca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a07f973efd45c15188ca5b64afe8f2a431fc49da885ce3473aca30f18230bd9567a0070547bf249b370121ae7bfcf64c421a91c25b4a694b1982b1f473138d69bb22a057b9a7532db0ead6850099e396471c6ab4b1c1970850d259abe2e1e8f4003d51b90100c401a002c0040080d10018404420012080006908000402002006880044e0011025081804301200210000a0100010380010c1021000122280a4010140406809c822c00088b0290808200008b948a10401148608004108100414000000902800011485010882042204128012a00110480100210002ea0900400b010110010910080800006508800151002142001a08002050001781a82110008000109a2a0885180200000658028e000001010409089600268470040042008020900052a85800806910100200020800130088060882000042c40010038002008100000840046040583cc00902840010209040a1000055011001342c408089400620a08000142c0080840783ee918401c9c3808371781a8466fbb6db80a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f846a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", + "0xf90244a012dfd2e2be4bcdd6b79eac25fb75a3fc4d755aa463acfc7ff80f3bf4ec49353aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0e49a1cb205090a958479f62241d3c812164630f09859538b98f20929700832caa0fb422fe08fca21bf0de2f413bee27c3ff3436ea54e32587238ce182d6dc1fb19a0274c2dbc71d835379c18401e3268e7c4f009b670b9a0ddca04743b7b0b65a111b90100005030021000000300001880204000001200020c000020000840000042c009000d08100030000108004000000000210800100442000022082040004040600000000280008008308a4000002850000000008400a02008000000210000000000000000010006040000000011000000889080004000200a00808000001208480908002000010002300060000202010180200100500080000000020000000a1004018a00001001000080300108208000000000000000000000090080408300000040400001020004240028008006004200000805800002880300000000084800200000300009002000000800001000000100000a011010902a00800010040001000080840783ee908401c9c3808335bb028466fbb6d980a0bc24644d93f212885acc3a93836ba214b962f7508721517fde36b89841d126638800000000000000008301f8dea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a080c2a58ed1b8b5bd35567d8dba40773b50e4bbe0b5f0e68b2a8a0d79c6619dae", + "0xf90244a0186b3f6370955f23ec37702b09582d6425ddfda544cb413ac327ef7f572f5b56a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0a6c0e65d726f0bfd262c65adafef031343d8950aed130b5fcfe27b1bef2212d5a0183a4a9f9dd4440ab81732a15891f6fd598f676df500c46a5dfcc24bb3278fc9a0440271bf3661f283439affb6cc2c3bc7903450f33ef3fa59a0205b3de7c73c65b90100881021024102000000000080002000002880012a000181080004000044c0010005081124212000a0002016900241201000000040810322840400080050600000008c8000000800080100600900a00000008001000308080001402040000044048008010026048248000090000000386204210000006808408010011000882008000000010080002000900a20000120201020148280200040040400004a4020008201c00052020400000021008008040018000000200400000090001080000400c400000200000000210000062042020820400004808022008400004840002010003000412020400009040002022001000000000001800000828008800001000080840783ee8f8401c9c380833f80448466fbb6d780a09996ce9a05bb1040afb647edc64c2c757853aacebbac768bbb021593fb1e501d8800000000000000008301f934a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a061fe46939ae209665c1dd0107123cd3e34c67ae2e0f21ef5adda87929dedc8eb", + ] + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + expect(await hashiProver.getStorageValue(correctProof)).to.be.deep.eq(["0xb56d157e7f5a"]) + } }) it("should not be able to get the value using ancestral blocks because of a conflict", async () => { - const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS] - wrongProof[4] = [ - "0xf90256a06f14ee388c6004c9f591c05cc94509906ebcc57e6ce9d7e65c52aa7da6f530e7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495222290dd7278aa3ddd389cc1e1d165cc4bafe5a07604903f485d83bda3b1333e28dec61ff3191fef0423ffce44abe02033b323d3a09c6967c2262b8e5aaf07f422806fa22eed9bd05898a71ef3435eb27e258ed240a061cf3a1b00a7ea8e1b8e4a921dbd9af3c73e9ec8646e9884b7936b74e011e05ab901005d61447fd94d1ba8d69022f0b7891c8486f9ae204a03b3b61bbbc905e371ecd613dfbe02ad85113252082314a8e78d016af918d9afd27030b5b7e890842a2f8058103e8c1640a87cd82c733d21e13afc3ce5e133ddd7fd3180a816dc8bfeeaa516555f3bf2545536b6605c1ea8276edf7d076e9346d88e37e24372bec69daa45caa8fe68c4c5edccefefbf60abaa9abee6106cf1dd25dc4fff490c7bf4b1f47993d733a25880a8170f165ed3bb283d69644fb677d0fd763a07218f66249961719ff37e762cf33f76036277f9c2d9e3d5a2a0b6b70cbfbd548a717143e29e3ef4a0f9b17f9f37bc546d06e5d23e02b3c64e2e542f026cf1d4391ccdf19400dc6d8084013d48a48401c9c3808401476c588466edbad78f6265617665726275696c642e6f7267a00b4078ca7a27f9b2448fa3f32e04a269353f80273e6dc95153458475a84238b98800000000000000008502d39a9e8ea00a7c969c5cab15361767d22966b8c0e507572acd096d3bc87af306be3ceb52138080a077f861b303ce5dd4bd241707d60a82406df608caa18ec241e33b5d5a2de94bc2", - "0xf90257a034c4cec5ba48eef207f01dace9b74648f75423b99274d285eb51a28ea45a7746a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941f9090aae28b8a3dceadf281b0f12828e676c326a017cb8d562b6da86b898d1579f2c0252ca4fc673ddbece39b0181fe6341dbfbb1a0ae9cf403fc193494aabb363f25427aa1adfe15793abe5765d28b0b1537e0900ba0b950d9ad9c7de4e5bd031c14c6d3afd38f1639e1db56590c6abafacae1e8be9bb9010055b5d41511013102900308208e003834d0c002308b480102a0a90901861621a7664ca1054060d40153aa1b99d74229a5c69380c489626d9027c9635a8d3ba580ed1ddc2810e5ef3f788ac929c12470b06160a08901404f2232ac9d42d9fa0785854040174adb01b6a3dd900ac9098e9d842ee6f52e148f0aba80cab721886001aa28bbd6804c7783a158856d63745f924614c4e1cd398c2a6525247746f4116aeb2021e09a52a018635202c32e2dce22379b9d05caf5986b252e4e0c401a11595d31264220a8210f01132022d6695481a4a02847113ce09583c7220200c6603891f33e680597a840000416a199101be82c29d000738c21d03c3b99150db214078084013d48a38401c9c38083b3f8218466edbacb917273796e632d6275696c6465722e78797aa034169fa758cb3cb5d38e8c22af9b88c525474253da05ca76b683f0c6ef922cee8800000000000000008502e776c769a01c91a492ffa0281242fdcb78078b290d5b055505d1872498d611f8cf295496818080a0686d3a40a3dd6df623831fd87b3c54877f9717001c997f9f9e1758c864df5634", - "0xf9025ba03f60781072e20bd526b224ff426c9784c24a949e977ad855585fc76c897d509fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495222290dd7278aa3ddd389cc1e1d165cc4bafe5a021c619739b6e81e67572203fb27f00c390e605a6fef0fe41c59f226853b082aba050885bd6330e2d1e68c236f561bcea587cfde066214e1fd0ca396d5574685a1da00f98eb31cf5b863de6be609e3389a276cdd0f5247ab142bba2210bcb5133d7d7b9010013f1cd759bd4d129b3bc004786899411332acb21690da0fe8cad091d3a35e08220c245663a4a52b01e4cda40d80f2fc1d2ad9988a862ee76672c504a032fc546d78187483ae99a39f89bd13ebde02ab494a3b071ed61dda0ac304eeaf83ac988d55bb445077b71e2a0c8c08d29496a11223b0387e5150c3620059c7c688dd1554a091f5492678d624c6d916063e43956c49dc589cd61013a60a345c7e1f65622bbbc4b9d5419e000ab03b6ef3ce98e82855d2f2748e6820988478101217e81ade1532542a5d11f555011218feb43548f47eb67c742392c7439c70e5be26174b5e5f32cfe83956d41a88413c522f2cfb0febf952d59b816e98a595fa1a18396e58084013d48a28401c9c38083d4d7678466edbabf8f6265617665726275696c642e6f7267a06f3f13b39fc3605558c21368794faf69b5edc4639f5f191fedbb9145f547fd7e8800000000000000008502ee08d0f0a0c3da7cb220020e2b5c78854d4e0822ed99dfeb75ff41a4066cd5c7b27e8943f88302000083040000a0f5decec30ba81918d464d9692fd3e0660f0f0247714899e77787b9b3e2fb2260", - ] - const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] - const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], - ) - await expect(hashiProverTest.getStorageValue(wrongProof)).to.be.revertedWithCustomError( - hashiProverTest, - "ConflictingBlockHeader", - ) + for (const hashiProver of hashiProvers) { + const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS] + wrongProof[4] = [ + "0xf90256a06f14ee388c6004c9f591c05cc94509906ebcc57e6ce9d7e65c52aa7da6f530e7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495222290dd7278aa3ddd389cc1e1d165cc4bafe5a07604903f485d83bda3b1333e28dec61ff3191fef0423ffce44abe02033b323d3a09c6967c2262b8e5aaf07f422806fa22eed9bd05898a71ef3435eb27e258ed240a061cf3a1b00a7ea8e1b8e4a921dbd9af3c73e9ec8646e9884b7936b74e011e05ab901005d61447fd94d1ba8d69022f0b7891c8486f9ae204a03b3b61bbbc905e371ecd613dfbe02ad85113252082314a8e78d016af918d9afd27030b5b7e890842a2f8058103e8c1640a87cd82c733d21e13afc3ce5e133ddd7fd3180a816dc8bfeeaa516555f3bf2545536b6605c1ea8276edf7d076e9346d88e37e24372bec69daa45caa8fe68c4c5edccefefbf60abaa9abee6106cf1dd25dc4fff490c7bf4b1f47993d733a25880a8170f165ed3bb283d69644fb677d0fd763a07218f66249961719ff37e762cf33f76036277f9c2d9e3d5a2a0b6b70cbfbd548a717143e29e3ef4a0f9b17f9f37bc546d06e5d23e02b3c64e2e542f026cf1d4391ccdf19400dc6d8084013d48a48401c9c3808401476c588466edbad78f6265617665726275696c642e6f7267a00b4078ca7a27f9b2448fa3f32e04a269353f80273e6dc95153458475a84238b98800000000000000008502d39a9e8ea00a7c969c5cab15361767d22966b8c0e507572acd096d3bc87af306be3ceb52138080a077f861b303ce5dd4bd241707d60a82406df608caa18ec241e33b5d5a2de94bc2", + "0xf90257a034c4cec5ba48eef207f01dace9b74648f75423b99274d285eb51a28ea45a7746a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941f9090aae28b8a3dceadf281b0f12828e676c326a017cb8d562b6da86b898d1579f2c0252ca4fc673ddbece39b0181fe6341dbfbb1a0ae9cf403fc193494aabb363f25427aa1adfe15793abe5765d28b0b1537e0900ba0b950d9ad9c7de4e5bd031c14c6d3afd38f1639e1db56590c6abafacae1e8be9bb9010055b5d41511013102900308208e003834d0c002308b480102a0a90901861621a7664ca1054060d40153aa1b99d74229a5c69380c489626d9027c9635a8d3ba580ed1ddc2810e5ef3f788ac929c12470b06160a08901404f2232ac9d42d9fa0785854040174adb01b6a3dd900ac9098e9d842ee6f52e148f0aba80cab721886001aa28bbd6804c7783a158856d63745f924614c4e1cd398c2a6525247746f4116aeb2021e09a52a018635202c32e2dce22379b9d05caf5986b252e4e0c401a11595d31264220a8210f01132022d6695481a4a02847113ce09583c7220200c6603891f33e680597a840000416a199101be82c29d000738c21d03c3b99150db214078084013d48a38401c9c38083b3f8218466edbacb917273796e632d6275696c6465722e78797aa034169fa758cb3cb5d38e8c22af9b88c525474253da05ca76b683f0c6ef922cee8800000000000000008502e776c769a01c91a492ffa0281242fdcb78078b290d5b055505d1872498d611f8cf295496818080a0686d3a40a3dd6df623831fd87b3c54877f9717001c997f9f9e1758c864df5634", + "0xf9025ba03f60781072e20bd526b224ff426c9784c24a949e977ad855585fc76c897d509fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479495222290dd7278aa3ddd389cc1e1d165cc4bafe5a021c619739b6e81e67572203fb27f00c390e605a6fef0fe41c59f226853b082aba050885bd6330e2d1e68c236f561bcea587cfde066214e1fd0ca396d5574685a1da00f98eb31cf5b863de6be609e3389a276cdd0f5247ab142bba2210bcb5133d7d7b9010013f1cd759bd4d129b3bc004786899411332acb21690da0fe8cad091d3a35e08220c245663a4a52b01e4cda40d80f2fc1d2ad9988a862ee76672c504a032fc546d78187483ae99a39f89bd13ebde02ab494a3b071ed61dda0ac304eeaf83ac988d55bb445077b71e2a0c8c08d29496a11223b0387e5150c3620059c7c688dd1554a091f5492678d624c6d916063e43956c49dc589cd61013a60a345c7e1f65622bbbc4b9d5419e000ab03b6ef3ce98e82855d2f2748e6820988478101217e81ade1532542a5d11f555011218feb43548f47eb67c742392c7439c70e5be26174b5e5f32cfe83956d41a88413c522f2cfb0febf952d59b816e98a595fa1a18396e58084013d48a28401c9c38083d4d7678466edbabf8f6265617665726275696c642e6f7267a06f3f13b39fc3605558c21368794faf69b5edc4639f5f191fedbb9145f547fd7e8800000000000000008502ee08d0f0a0c3da7cb220020e2b5c78854d4e0822ed99dfeb75ff41a4066cd5c7b27e8943f88302000083040000a0f5decec30ba81918d464d9692fd3e0660f0f0247714899e77787b9b3e2fb2260", + ] + const sourceChainId = ACCOUNT_AND_STORAGE_PROOF[0] + const blockNumber = ACCOUNT_AND_STORAGE_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], + ) + await expect(hashiProver.getStorageValue(wrongProof)).to.be.revertedWithCustomError( + hashiProver, + "ConflictingBlockHeader", + ) + } }) it("should be able to read the event topics and data", async () => { - const sourceChainId = RECEIPT_PROOF[0] - const blockNumber = RECEIPT_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0x4a95d1ff4f70678c282ef4c88aee8627798dc6957726bb27b16bf206875b5b7e"], - ) - expect(await hashiProverTest.getEventValues(RECEIPT_PROOF)).to.be.eq( - "0xf85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680", - ) + for (const hashiProver of hashiProvers) { + const sourceChainId = RECEIPT_PROOF[0] + const blockNumber = RECEIPT_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0x4a95d1ff4f70678c282ef4c88aee8627798dc6957726bb27b16bf206875b5b7e"], + ) + expect(await hashiProver.getEventValues(RECEIPT_PROOF)).to.be.eq( + "0xf85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680", + ) + } }) it("should not be able to get the event topics and data if the proof is not valid", async () => { - const sourceChainId = RECEIPT_PROOF[0] - const blockNumber = RECEIPT_PROOF[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0x4a95d1ff4f70678c282ef4c88aee8627798dc6957726bb27b16bf206875b5b7e"], - ) - const wrongProof = [...RECEIPT_PROOF] - wrongProof[5] = [ - "0xf851a043d1a97a67ace1b4fcf400c97b64833e363f929339269b5f08316efe15bb744280808080808080a0c6671ab0c8145b7e995558f60b59fc3ab0afd34db7ba64c70268da26e6f652078080808080808080", - "0xf901f180a022532ca66e2a83977e663b41605e7e2df76bc896e12fc53dce0c5b95ed7f4367a0fd882e481b284515091c4eace0556fd4bf36261a282c4dbe14a9813af1a73504a04b64fbdf1b5db465262c0c4a07d8d1a69034fff72db3e02d6661743522b7c7d7a0f3e1c56f139f509c3bd8cc1546737d231ee006b4f760f9d754b1ce80b64ceb31a0095b2d77ffa53c424fe4cdaf377d3bea5129bc21e95046f267b0d429bf112405a0156430f22abbf89c225643a24d9a97a7fe5832d15df48ec934f56a5860431a8aa040c1f34f5f45ff6d5a717795fc90d520d5080994a10fc487af7a60557b367c5ca0dd8bd9a505b52c9249dc171eea453972bc5261f876553296c8a6186c20f4143da075f0a228baf7eea3111db5ca77d9901bd99109fa3c0d8d3c0e53280ea92e8ec7a0676127922e8aa2da69ca3fd4802d559275d6fd4f5f51f86801e0fcdbc65cdc0ea0e1af98a5d5db3b2b9beb67e7fe333e669b8bc7c73cac1b6c3f96d68670d87422a06ac3e127bdadf66bd1352a7666934c3ab258bb4483f2d9c285aeec2012fed133a0e64c4cb299540f0ca821a86fa4d0ffdd17ef4f997ad121ebec941cedaf2c9390a0977a40d5cb87002b9d8dbaf25667b3b0dd1bd089b49e6c5de4edc7fd2b45cf5fa064756251d84bca534b9408b1c3b5ed3b415bb06e52ac01d37b6c205ff54e7f4380", - "0xf90ad720b90ad302f90acf01832fce87b9010000010000000400000000010000020000800000000000400100000000000000000000000000000000000000500000000000000000000000000000000000000000000010002400000000200000000000000000000010010008004000000000000000000200000000800500000000000000000008000100000000000000000000000800010000000200000000000000000008000002000000000000000004000000000080001000080800100000000000000000000000004000000000000000000000100004000000000000000000000000000000000000200000000080020000000010080000010008000000000800100060000000000000000000000000100000f909c4f85a94a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0bf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0bf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000009aa56119ab6bf672e22eea5c4735446101bd46d8f87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0ba000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000009aa56119ab6bf672e22eea5c4735446101bd46d80000000000000000000000000000000000000000000000000000000000000001f85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000007388755e0a5b867f30168ea89f2d42db2d5cb918f87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000b981b2c0c3db52c316d30df76cc48fd167ed87eda000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000007388755e0a5b867f30168ea89f2d42db2d5cb9180000000000000000000000000000000000000000000000000000000000000001f85a94ca71fa74c9682518ff2489b902648e6c2745573bf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94ca71fa74c9682518ff2489b902648e6c2745573bf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e44a29d8d2197e80085986953d52566d10eaacacf87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000ca71fa74c9682518ff2489b902648e6c2745573ba000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab840000000000000000000000000e44a29d8d2197e80085986953d52566d10eaacac0000000000000000000000000000000000000000000000000000000000000001f85a94de8507bb18616ce211638fb898e452f5486b916ef842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94de8507bb18616ce211638fb898e452f5486b916ef842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000007e1306f8adf9125b3795dfefff35c1a80be5ebeef87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000de8507bb18616ce211638fb898e452f5486b916ea000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000007e1306f8adf9125b3795dfefff35c1a80be5ebee0000000000000000000000000000000000000000000000000000000000000001", - ] - await expect(hashiProverTest.getEventValues(wrongProof)).to.be.revertedWith( - "MerkleTrie: invalid large internal hash", - ) + for (const hashiProver of hashiProvers) { + const sourceChainId = RECEIPT_PROOF[0] + const blockNumber = RECEIPT_PROOF[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0x4a95d1ff4f70678c282ef4c88aee8627798dc6957726bb27b16bf206875b5b7e"], + ) + const wrongProof = [...RECEIPT_PROOF] + wrongProof[5] = [ + "0xf851a043d1a97a67ace1b4fcf400c97b64833e363f929339269b5f08316efe15bb744280808080808080a0c6671ab0c8145b7e995558f60b59fc3ab0afd34db7ba64c70268da26e6f652078080808080808080", + "0xf901f180a022532ca66e2a83977e663b41605e7e2df76bc896e12fc53dce0c5b95ed7f4367a0fd882e481b284515091c4eace0556fd4bf36261a282c4dbe14a9813af1a73504a04b64fbdf1b5db465262c0c4a07d8d1a69034fff72db3e02d6661743522b7c7d7a0f3e1c56f139f509c3bd8cc1546737d231ee006b4f760f9d754b1ce80b64ceb31a0095b2d77ffa53c424fe4cdaf377d3bea5129bc21e95046f267b0d429bf112405a0156430f22abbf89c225643a24d9a97a7fe5832d15df48ec934f56a5860431a8aa040c1f34f5f45ff6d5a717795fc90d520d5080994a10fc487af7a60557b367c5ca0dd8bd9a505b52c9249dc171eea453972bc5261f876553296c8a6186c20f4143da075f0a228baf7eea3111db5ca77d9901bd99109fa3c0d8d3c0e53280ea92e8ec7a0676127922e8aa2da69ca3fd4802d559275d6fd4f5f51f86801e0fcdbc65cdc0ea0e1af98a5d5db3b2b9beb67e7fe333e669b8bc7c73cac1b6c3f96d68670d87422a06ac3e127bdadf66bd1352a7666934c3ab258bb4483f2d9c285aeec2012fed133a0e64c4cb299540f0ca821a86fa4d0ffdd17ef4f997ad121ebec941cedaf2c9390a0977a40d5cb87002b9d8dbaf25667b3b0dd1bd089b49e6c5de4edc7fd2b45cf5fa064756251d84bca534b9408b1c3b5ed3b415bb06e52ac01d37b6c205ff54e7f4380", + "0xf90ad720b90ad302f90acf01832fce87b9010000010000000400000000010000020000800000000000400100000000000000000000000000000000000000500000000000000000000000000000000000000000000010002400000000200000000000000000000010010008004000000000000000000200000000800500000000000000000008000100000000000000000000000800010000000200000000000000000008000002000000000000000004000000000080001000080800100000000000000000000000004000000000000000000000100004000000000000000000000000000000000000200000000080020000000010080000010008000000000800100060000000000000000000000000100000f909c4f85a94a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0bf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0bf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000009aa56119ab6bf672e22eea5c4735446101bd46d8f87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000a8d3c1e744fcc68c893a32a9f19a49d5bc76fd0ba000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000009aa56119ab6bf672e22eea5c4735446101bd46d80000000000000000000000000000000000000000000000000000000000000001f85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000007388755e0a5b867f30168ea89f2d42db2d5cb918f87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000b981b2c0c3db52c316d30df76cc48fd167ed87eda000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000007388755e0a5b867f30168ea89f2d42db2d5cb9180000000000000000000000000000000000000000000000000000000000000001f85a94ca71fa74c9682518ff2489b902648e6c2745573bf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94ca71fa74c9682518ff2489b902648e6c2745573bf842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c2260000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e44a29d8d2197e80085986953d52566d10eaacacf87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000ca71fa74c9682518ff2489b902648e6c2745573ba000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab840000000000000000000000000e44a29d8d2197e80085986953d52566d10eaacac0000000000000000000000000000000000000000000000000000000000000001f85a94de8507bb18616ce211638fb898e452f5486b916ef842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680f9011b94de8507bb18616ce211638fb898e452f5486b916ef842a0141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8a00000000000000000000000004e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67b8c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000002dd68b007b46fbe91b9a7c3eda5a7a1063cb5b4700000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22600000000000000000000000000000000000000000000000000000000000000010000000000000000000000007e1306f8adf9125b3795dfefff35c1a80be5ebeef87a944e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67f842a04f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235a0000000000000000000000000de8507bb18616ce211638fb898e452f5486b916ea000000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762f8799424f6f36a551fe6008fa80afcff1d6ace182ead2be1a0db3dd2da8ea81566d4f4c29c152977ba57d38e7eed4b61fb95dfaceb177409bab8400000000000000000000000007e1306f8adf9125b3795dfefff35c1a80be5ebee0000000000000000000000000000000000000000000000000000000000000001", + ] + await expect(hashiProver.getEventValues(wrongProof)).to.be.revertedWith("MerkleTrie: invalid large internal hash") + } }) it("should be able to read the event topics and data using ancestral blocks", async () => { - const sourceChainId = RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS[0] - const blockNumber = RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS[1] - await adapter.setHashes( - sourceChainId, - [blockNumber], - ["0x316e3ae654c0f73f45c71768629c7933f2d444b04e223f1afcb1ebf244b744e3"], - ) - expect(await hashiProverTest.getEventValues(RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS)).to.be.eq( - "0xf85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680", - ) + for (const hashiProver of hashiProvers) { + const sourceChainId = RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS[0] + const blockNumber = RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS[1] + await adapter.setHashes( + sourceChainId, + [blockNumber], + ["0x316e3ae654c0f73f45c71768629c7933f2d444b04e223f1afcb1ebf244b744e3"], + ) + expect(await hashiProver.getEventValues(RECEIPT_PROOF_WITH_ANCESTRAL_BLOCKS)).to.be.eq( + "0xf85a94b981b2c0c3db52c316d30df76cc48fd167ed87edf842a0ecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f8440a000000000000000000000000075cf11467937ce3f2f357ce24ffc3dbf8fd5c22680", + ) + } }) }) diff --git a/yarn.lock b/yarn.lock index 38ee2126..88e1b00c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,39 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== +"@aws-crypto/sha256-js@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz#02acd1a1fda92896fc5a28ec7c6e164644ea32fc" + integrity sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g== + dependencies: + "@aws-crypto/util" "^1.2.2" + "@aws-sdk/types" "^3.1.0" + tslib "^1.11.1" + +"@aws-crypto/util@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-1.2.2.tgz#b28f7897730eb6538b21c18bd4de22d0ea09003c" + integrity sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg== + dependencies: + "@aws-sdk/types" "^3.1.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/types@^3.1.0": + version "3.686.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.686.0.tgz#01aa5307c727de9e69969c538f99ae8b53f1074f" + integrity sha512-xFnrb3wxOoJcW2Xrh63ZgFo5buIu9DF7bOHnwoUxHdNpUXicUh0AHw85TjXxyxIAd0d1psY/DU7QHoNI3OswgQ== + dependencies: + "@smithy/types" "^3.6.0" + tslib "^2.6.2" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + "@axelar-network/axelar-gmp-sdk-solidity@5.6.4": version "5.6.4" resolved "https://registry.yarnpkg.com/@axelar-network/axelar-gmp-sdk-solidity/-/axelar-gmp-sdk-solidity-5.6.4.tgz#fe224ff039f86f1cbf72d9b53339a8354f531b65" @@ -435,7 +468,7 @@ "@ethereumjs/rlp" "^5.0.2" ethereum-cryptography "^2.2.1" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -1123,6 +1156,66 @@ table "^6.8.0" undici "^5.14.0" +"@nomicfoundation/slang-darwin-arm64@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.17.0.tgz#8cded3c24322624e3b6618760caba8e840bd1c1d" + integrity sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA== + +"@nomicfoundation/slang-darwin-x64@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.17.0.tgz#6ebeb33a2ced89fc6023f6cda4af96403486038a" + integrity sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g== + +"@nomicfoundation/slang-linux-arm64-gnu@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.17.0.tgz#41c7e57a9b1a3aee6911f0cab22e683c149fb470" + integrity sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw== + +"@nomicfoundation/slang-linux-arm64-musl@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.17.0.tgz#9c4b51689274ae75c2c8a4cddd2e1cc0a79c191d" + integrity sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA== + +"@nomicfoundation/slang-linux-x64-gnu@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.17.0.tgz#c3a3b6a7b775fc617832958d10e6664bf86d39d0" + integrity sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg== + +"@nomicfoundation/slang-linux-x64-musl@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.17.0.tgz#725118ff99a7217b9f1d1bd84411d9442084077d" + integrity sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ== + +"@nomicfoundation/slang-win32-arm64-msvc@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.17.0.tgz#9c8bc4ccf21eaaac0cfcb6d3954ede4e2dea4c02" + integrity sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q== + +"@nomicfoundation/slang-win32-ia32-msvc@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.17.0.tgz#3fc5d00a3f8c1d85a5e94146af78a5526a4f3d27" + integrity sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg== + +"@nomicfoundation/slang-win32-x64-msvc@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.17.0.tgz#f6a5e3250fa07cbda49151edeb80f09090e5b71a" + integrity sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA== + +"@nomicfoundation/slang@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.17.0.tgz#d9c25cd711ebf3490c9d0c99e9b4ca2481341a6b" + integrity sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ== + dependencies: + "@nomicfoundation/slang-darwin-arm64" "0.17.0" + "@nomicfoundation/slang-darwin-x64" "0.17.0" + "@nomicfoundation/slang-linux-arm64-gnu" "0.17.0" + "@nomicfoundation/slang-linux-arm64-musl" "0.17.0" + "@nomicfoundation/slang-linux-x64-gnu" "0.17.0" + "@nomicfoundation/slang-linux-x64-musl" "0.17.0" + "@nomicfoundation/slang-win32-arm64-msvc" "0.17.0" + "@nomicfoundation/slang-win32-ia32-msvc" "0.17.0" + "@nomicfoundation/slang-win32-x64-msvc" "0.17.0" + "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" @@ -1222,6 +1315,56 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.3.tgz#ff6ee919fc2a1abaf72b22814bfb72ed129ec137" integrity sha512-tDBopO1c98Yk7Cv/PZlHqrvtVjlgK5R4J6jxLwoO7qxK4xqOiZG+zSkIvGFpPZ0ikc3QOED3plgdqjgNTnBc7g== +"@openzeppelin/defender-base-client@^1.46.0": + version "1.54.6" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-base-client/-/defender-base-client-1.54.6.tgz#b65a90dba49375ac1439d638832382344067a0b9" + integrity sha512-PTef+rMxkM5VQ7sLwLKSjp2DBakYQd661ZJiSRywx+q/nIpm3B/HYGcz5wPZCA5O/QcEP6TatXXDoeMwimbcnw== + dependencies: + amazon-cognito-identity-js "^6.0.1" + async-retry "^1.3.3" + axios "^1.4.0" + lodash "^4.17.19" + node-fetch "^2.6.0" + +"@openzeppelin/hardhat-upgrades@1.28.0": + version "1.28.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.28.0.tgz#6361f313a8a879d8a08a5e395acf0933bc190950" + integrity sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ== + dependencies: + "@openzeppelin/defender-base-client" "^1.46.0" + "@openzeppelin/platform-deploy-client" "^0.8.0" + "@openzeppelin/upgrades-core" "^1.27.0" + chalk "^4.1.0" + debug "^4.1.1" + proper-lockfile "^4.1.1" + +"@openzeppelin/platform-deploy-client@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.8.0.tgz#af6596275a19c283d6145f0128cc1247d18223c1" + integrity sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA== + dependencies: + "@ethersproject/abi" "^5.6.3" + "@openzeppelin/defender-base-client" "^1.46.0" + axios "^0.21.2" + lodash "^4.17.19" + node-fetch "^2.6.0" + +"@openzeppelin/upgrades-core@^1.27.0": + version "1.40.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.40.0.tgz#f01647afb99b46356b3e7b98e3b2c7f864d85add" + integrity sha512-4bPSXdEqHsNRL5T1ybPLneWGYjzGl6XWGWkv7aUoFFgz8mOdarstRBX1Wi4XJFw6IeHPUI7mMSQr2jdz8Y2ypQ== + dependencies: + "@nomicfoundation/slang" "^0.17.0" + cbor "^9.0.0" + chalk "^4.1.0" + compare-versions "^6.0.0" + debug "^4.1.1" + ethereumjs-util "^7.0.3" + minimatch "^9.0.5" + minimist "^1.2.7" + proper-lockfile "^4.1.1" + solidity-ast "^0.4.51" + "@polytope-labs/ismp-solidity@^0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@polytope-labs/ismp-solidity/-/ismp-solidity-0.7.4.tgz#00a9e02f2eb0cdbb444fb3f244dc8199c5bfb685" @@ -1388,6 +1531,13 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" +"@smithy/types@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.6.0.tgz#03a52bfd62ee4b7b2a1842c8ae3ada7a0a5ff3a4" + integrity sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w== + dependencies: + tslib "^2.6.2" + "@solana/buffer-layout@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" @@ -2088,6 +2238,17 @@ ajv@^8.0.1, ajv@^8.11.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +amazon-cognito-identity-js@^6.0.1: + version "6.3.12" + resolved "https://registry.yarnpkg.com/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz#af73df033094ad4c679c19cf6122b90058021619" + integrity sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg== + dependencies: + "@aws-crypto/sha256-js" "1.2.2" + buffer "4.9.2" + fast-base64-decode "^1.0.0" + isomorphic-unfetch "^3.0.0" + js-cookie "^2.2.1" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -2226,6 +2387,13 @@ async-mutex@^0.4.0: dependencies: tslib "^2.4.0" +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + async@1.x: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -2246,14 +2414,14 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -axios@^0.21.1: +axios@^0.21.1, axios@^0.21.2: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" -axios@^1.5.1: +axios@^1.4.0, axios@^1.5.1: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -2274,7 +2442,7 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" -base64-js@^1.3.0, base64-js@^1.3.1: +base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2445,6 +2613,15 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== +buffer@4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -2527,6 +2704,13 @@ cbor@^8.1.0: dependencies: nofilter "^3.1.0" +cbor@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.2.tgz#536b4f2d544411e70ec2b19a2453f10f83cd9fdb" + integrity sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ== + dependencies: + nofilter "^3.1.0" + chai-as-promised@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" @@ -2761,6 +2945,11 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" +compare-versions@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.1.tgz#7af3cc1099ba37d244b3145a9af5201b629148a9" + integrity sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3382,7 +3571,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.1.4: +ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -3528,6 +3717,11 @@ eyes@^0.1.8: resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== +fast-base64-decode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" + integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3996,7 +4190,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -4268,7 +4462,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.2.1: +ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -4456,21 +4650,29 @@ is-wsl@^2.1.1: dependencies: is-docker "^2.0.0" +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isomorphic-unfetch@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" + integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== + dependencies: + node-fetch "^2.6.1" + unfetch "^4.2.0" + isomorphic-ws@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" @@ -4504,6 +4706,11 @@ jayson@^4.1.1: uuid "^8.3.2" ws "^7.5.10" +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + js-sdsl@^4.1.4: version "4.4.2" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" @@ -4787,7 +4994,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5014,6 +5221,13 @@ minimatch@^5.0.1, minimatch@^5.1.6: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -5023,7 +5237,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -5151,7 +5365,7 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@^2.7.0: +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -5551,6 +5765,15 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +proper-lockfile@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -5765,6 +5988,16 @@ resolve@^1.1.6, resolve@^1.10.0, resolve@^1.8.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6015,7 +6248,7 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.3: +signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -6100,6 +6333,11 @@ solhint@^3.3.7: optionalDependencies: prettier "^2.8.3" +solidity-ast@^0.4.51: + version "0.4.59" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.59.tgz#290a2815aef70a61092591ab3e991da080ae5931" + integrity sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g== + solidity-bytes-utils@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/solidity-bytes-utils/-/solidity-bytes-utils-0.8.2.tgz#763d6a02fd093e93b3a97b742e97d540e66c29bd" @@ -6528,11 +6766,16 @@ tslib@2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.3.1, tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^2.4.0: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" @@ -6690,6 +6933,11 @@ undici@^5.14.0: dependencies: "@fastify/busboy" "^2.0.0" +unfetch@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" From 0799557cfd668d718e3a3de435f06dcba0616092 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 12 Nov 2024 14:31:52 +0100 Subject: [PATCH 2/5] feat(evm): adds HashiProverLib and rm AccountAndStorageProof.storageHash --- .../evm/contracts/interfaces/IHashiProver.sol | 44 ---- packages/evm/contracts/prover/HashiProver.sol | 178 +------------- .../evm/contracts/prover/HashiProverLib.sol | 230 ++++++++++++++++++ .../contracts/prover/HashiProverStructs.sol | 29 +++ .../prover/HashiProverUpgradeable.sol | 177 +------------- .../evm/contracts/test/HashiProverTest.sol | 5 +- .../test/HashiProverTestUpgradeable.sol | 7 +- 7 files changed, 275 insertions(+), 395 deletions(-) delete mode 100644 packages/evm/contracts/interfaces/IHashiProver.sol create mode 100644 packages/evm/contracts/prover/HashiProverLib.sol create mode 100644 packages/evm/contracts/prover/HashiProverStructs.sol diff --git a/packages/evm/contracts/interfaces/IHashiProver.sol b/packages/evm/contracts/interfaces/IHashiProver.sol deleted file mode 100644 index 723ef8fc..00000000 --- a/packages/evm/contracts/interfaces/IHashiProver.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.0; - -/** - * @title IHashiProver - */ -interface IHashiProver { - struct AccountAndStorageProof { - uint256 chainId; - uint256 blockNumber; - bytes blockHeader; - uint256 ancestralBlockNumber; - bytes[] ancestralBlockHeaders; - address account; - bytes[] accountProof; - bytes32 storageHash; - bytes32[] storageKeys; - bytes[][] storageProof; - } - - struct ReceiptProof { - uint256 chainId; - uint256 blockNumber; - bytes blockHeader; - uint256 ancestralBlockNumber; - bytes[] ancestralBlockHeaders; - bytes[] receiptProof; - bytes transactionIndex; - uint256 logIndex; - } - - error AncestralBlockHeadersLengthReached(); - error BlockHeaderNotFound(); - error ConflictingBlockHeader(uint256 blockNumber, bytes32 ancestralBlockHeaderHash, bytes32 blockHeaderHash); - error InvalidAccount(); - error InvalidBlockHeader(); - error InvalidBlockHeaderLength(); - error InvalidLogIndex(); - error InvalidReceipt(); - error InvalidReceiptProof(); - error InvalidStorageHash(); - error InvalidStorageProofParams(); - error UnsupportedTxType(); -} diff --git a/packages/evm/contracts/prover/HashiProver.sol b/packages/evm/contracts/prover/HashiProver.sol index 59260e5b..a8db5f18 100644 --- a/packages/evm/contracts/prover/HashiProver.sol +++ b/packages/evm/contracts/prover/HashiProver.sol @@ -1,16 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; -import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; -import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; -import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol"; -import { IHashiProver } from "../interfaces/IHashiProver.sol"; -import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; - -contract HashiProver is IHashiProver { - using RLPReader for RLPReader.RLPItem; - using RLPReader for bytes; +import { HashiProverLib } from "./HashiProverLib.sol"; +import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +contract HashiProver { /// @notice Stores the address of the ShoyuBashi contract. address public immutable SHOYU_BASHI; @@ -34,23 +28,7 @@ contract HashiProver is IHashiProver { * @return bytes The RLP-encoded event corresponding to the specified `logIndex`. */ function verifyForeignEvent(ReceiptProof calldata proof) internal view returns (bytes memory) { - bytes memory blockHeader = _checkBlockHeaderAgainstHashi( - proof.chainId, - proof.blockNumber, - proof.blockHeader, - proof.ancestralBlockNumber, - proof.ancestralBlockHeaders - ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 receiptsRoot = bytes32(blockHeaderFields[5].toUint()); - - bytes memory value = MerkleTrie.get(proof.transactionIndex, proof.receiptProof, receiptsRoot); - RLPReader.RLPItem[] memory receiptFields = _extractReceiptFields(value); - if (receiptFields.length != 4) revert InvalidReceipt(); - - RLPReader.RLPItem[] memory logs = receiptFields[3].toList(); - if (proof.logIndex >= logs.length) revert InvalidLogIndex(); - return logs[proof.logIndex].toRlpBytes(); + return HashiProverLib.verifyForeignEvent(proof, SHOYU_BASHI); } /** @@ -64,158 +42,12 @@ contract HashiProver is IHashiProver { * - ancestralBlockHeaders: Array of block headers proving ancestry of the specified block. * - account: The account address whose storage is being verified. * - accountProof: Proof data for locating the account in the state trie. - * - storageHash: Expected hash of the storage root for the account. * - storageKeys: Array of storage keys for which data is being verified. * - storageProof: Proof data for locating the storage values in the storage trie. * * @return bytes[] An array of storage values corresponding to the specified `storageKeys`. */ function verifyForeignStorage(AccountAndStorageProof calldata proof) internal view returns (bytes[] memory) { - bytes memory blockHeader = _checkBlockHeaderAgainstHashi( - proof.chainId, - proof.blockNumber, - proof.blockHeader, - proof.ancestralBlockNumber, - proof.ancestralBlockHeaders - ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 stateRoot = bytes32(blockHeaderFields[3].toUint()); - (, , bytes32 expectedStorageHash, ) = _verifyAccountProof(proof.account, stateRoot, proof.accountProof); - if (proof.storageHash != expectedStorageHash) revert InvalidStorageHash(); - return _verifyStorageProof(proof.storageHash, proof.storageKeys, proof.storageProof); - } - - /** - * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. - * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. - * If it doesn't match directly, it will verify the block by traversing ancestral blocks until a matching block header or ancestor is found. - * If no match is found, it reverts with `BlockHeaderNotFound`. - * @param chainId The chain ID associated with the block. - * @param blockNumber The number of the block to be checked. - * @param blockHeader The RLP-encoded header of the block. - * @param ancestralBlockNumber The block number of the ancestral block to be verified, if applicable. - * @param ancestralBlockHeaders An array of RLP-encoded headers for ancestral blocks. - * @return bytes The RLP-encoded block header if successfully verified. - */ - function _checkBlockHeaderAgainstHashi( - uint256 chainId, - uint256 blockNumber, - bytes memory blockHeader, - uint256 ancestralBlockNumber, - bytes[] memory ancestralBlockHeaders - ) private view returns (bytes memory) { - bytes32 blockHeaderHash = keccak256(blockHeader); - bytes32 currentBlockHeaderHash = IShoyuBashi(SHOYU_BASHI).getThresholdHash(chainId, blockNumber); - if (currentBlockHeaderHash == blockHeaderHash && ancestralBlockHeaders.length == 0) return blockHeader; - - for (uint256 i = 0; i < ancestralBlockHeaders.length; i++) { - RLPReader.RLPItem memory ancestralBlockHeaderRLP = RLPReader.toRlpItem(ancestralBlockHeaders[i]); - RLPReader.RLPItem[] memory ancestralBlockHeaderContent = ancestralBlockHeaderRLP.toList(); - - bytes32 blockParentHash = bytes32(ancestralBlockHeaderContent[0].toUint()); - uint256 currentAncestralBlockNumber = uint256(ancestralBlockHeaderContent[8].toUint()); - - bytes32 ancestralBlockHeaderHash = keccak256(ancestralBlockHeaders[i]); - if (ancestralBlockHeaderHash != currentBlockHeaderHash) - revert ConflictingBlockHeader( - currentAncestralBlockNumber, - ancestralBlockHeaderHash, - currentBlockHeaderHash - ); - - if (ancestralBlockNumber == currentAncestralBlockNumber) { - return ancestralBlockHeaders[i]; - } else { - currentBlockHeaderHash = blockParentHash; - } - } - - revert BlockHeaderNotFound(); - } - - /** - * @notice Extracts the fields of a transaction receipt from its RLP-encoded data. - * @dev This function handles different transaction types by setting the appropriate offset for RLP parsing. - * It adjusts the starting point based on the transaction type byte, then uses RLPReader to parse the fields. - * @param value The RLP-encoded transaction receipt. - * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. - */ - function _extractReceiptFields(bytes memory value) private pure returns (RLPReader.RLPItem[] memory) { - uint256 offset; - if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { - offset = 1; - } else if (value[0] >= 0xc0) { - offset = 0; - } else { - revert UnsupportedTxType(); - } - - uint256 memPtr; - assembly { - memPtr := add(value, add(0x20, mul(0x01, offset))) - } - - return RLPReader.RLPItem(value.length - offset, memPtr).toList(); - } - - /** - * @notice Verifies an account proof and extracts account fields from it. - * @dev This function uses a Merkle proof to verify the account state in a given state root. - * It retrieves and decodes the account data, checking the storage root and account structure. - * @param account The address of the account to verify. - * @param stateRoot The state root against which the account proof is verified. - * @param proof A Merkle proof required to verify the account. - * @return uint256 The nonce of the account. - * @return uint256 The balance of the account. - * @return bytes32 The storage root of the account. - * @return bytes32 The code hash of the account. - */ - function _verifyAccountProof( - address account, - bytes32 stateRoot, - bytes[] memory proof - ) private pure returns (uint256, uint256, bytes32, bytes32) { - bytes memory accountRlp = SecureMerkleTrie.get(abi.encodePacked(account), proof, stateRoot); - - bytes32 accountStorageRoot = bytes32(accountRlp.toRlpItem().toList()[2].toUint()); - if (accountStorageRoot.length == 0) revert InvalidStorageHash(); - RLPReader.RLPItem[] memory accountFields = accountRlp.toRlpItem().toList(); - if (accountFields.length != 4) revert InvalidAccount(); - // [nonce, balance, storageHash, codeHash] - return ( - accountFields[0].toUint(), - accountFields[1].toUint(), - bytes32(accountFields[2].toUint()), - bytes32(accountFields[3].toUint()) - ); - } - - /** - * @notice Verifies multiple storage proofs and retrieves the storage values associated with given keys. - * @dev This function iterates over provided storage keys and their respective proofs, - * using a Merkle proof to verify each storage value against the specified storage hash. - * @param storageHash The root hash of the storage trie for the account being verified. - * @param storageKeys An array of storage keys for which values need to be verified. - * @param proof A 2D array of Merkle proof elements for each storage key. - * @return bytes[] An array of storage values corresponding to each storage key. - */ - function _verifyStorageProof( - bytes32 storageHash, - bytes32[] memory storageKeys, - bytes[][] memory proof - ) private pure returns (bytes[] memory) { - bytes[] memory results = new bytes[](proof.length); - if (storageKeys.length == 0 || proof.length == 0 || storageKeys.length != proof.length) - revert InvalidStorageProofParams(); - for (uint256 i = 0; i < proof.length; ) { - RLPReader.RLPItem memory item = RLPReader.toRlpItem( - SecureMerkleTrie.get(abi.encode(storageKeys[i]), proof[i], storageHash) - ); - results[i] = item.toBytes(); - unchecked { - ++i; - } - } - return results; + return HashiProverLib.verifyForeignStorage(proof, SHOYU_BASHI); } } diff --git a/packages/evm/contracts/prover/HashiProverLib.sol b/packages/evm/contracts/prover/HashiProverLib.sol new file mode 100644 index 00000000..a60222cf --- /dev/null +++ b/packages/evm/contracts/prover/HashiProverLib.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; +import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; +import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol"; +import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; +import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; + +library HashiProverLib { + using RLPReader for RLPReader.RLPItem; + using RLPReader for bytes; + + error BlockHeaderNotFound(); + error ConflictingBlockHeader(uint256 blockNumber, bytes32 ancestralBlockHeaderHash, bytes32 blockHeaderHash); + error InvalidAccount(); + error InvalidLogIndex(); + error InvalidReceipt(); + error InvalidStorageHash(); + error InvalidStorageProofParams(); + error UnsupportedTxType(); + + /** + * @dev Verifies and retrieves a specific event from a transaction receipt in a foreign blockchain. + * + * @param proof A `ReceiptProof` struct containing proof details: + * - chainId: The chain ID of the foreign blockchain. + * - blockNumber: If ancestralBlockNumber is 0, then blockNumber represents the block where the transaction occurred and is available in Hashi. + * - blockHeader: The header of the specified block. + * - ancestralBlockNumber: If provided, this is the block number where the transaction took place. In this case, blockNumber is the block whose header is accessible in Hashi. + * - ancestralBlockHeaders: Array of block headers to prove the ancestry of the specified block. + * - receiptProof: Proof data for locating the receipt in the Merkle Trie. + * - transactionIndex: Index of the transaction within the block. + * - logIndex: The specific log index within the transaction receipt. + * @param shoyuBashi The address of ShoyuBashi contract + * + * @return bytes The RLP-encoded event corresponding to the specified `logIndex`. + */ + function verifyForeignEvent(ReceiptProof calldata proof, address shoyuBashi) internal view returns (bytes memory) { + bytes memory blockHeader = checkBlockHeaderAgainstHashi( + proof.chainId, + proof.blockNumber, + proof.blockHeader, + proof.ancestralBlockNumber, + proof.ancestralBlockHeaders, + shoyuBashi + ); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); + bytes32 receiptsRoot = bytes32(blockHeaderFields[5].toUint()); + + bytes memory value = MerkleTrie.get(proof.transactionIndex, proof.receiptProof, receiptsRoot); + RLPReader.RLPItem[] memory receiptFields = extractReceiptFields(value); + if (receiptFields.length != 4) revert InvalidReceipt(); + + RLPReader.RLPItem[] memory logs = receiptFields[3].toList(); + if (proof.logIndex >= logs.length) revert InvalidLogIndex(); + return logs[proof.logIndex].toRlpBytes(); + } + + /** + * @dev Verifies foreign storage data for a specified account on a foreign blockchain. + * + * @param proof An `AccountAndStorageProof` struct containing proof details: + * - chainId: The chain ID of the foreign blockchain. + * - blockNumber: If ancestralBlockNumber is 0, then blockNumber represents the block where the transaction occurred and is available in Hashi. + * - blockHeader: The header of the specified block. + * - ancestralBlockNumber: If provided, this is the block number where the transaction took place. In this case, blockNumber is the block whose header is accessible in Hashi. + * - ancestralBlockHeaders: Array of block headers proving ancestry of the specified block. + * - account: The account address whose storage is being verified. + * - accountProof: Proof data for locating the account in the state trie. + * - storageKeys: Array of storage keys for which data is being verified. + * - storageProof: Proof data for locating the storage values in the storage trie. + * @param shoyuBashi The address of ShoyuBashi contract + * + * @return bytes[] An array of storage values corresponding to the specified `storageKeys`. + */ + function verifyForeignStorage( + AccountAndStorageProof calldata proof, + address shoyuBashi + ) internal view returns (bytes[] memory) { + bytes memory blockHeader = checkBlockHeaderAgainstHashi( + proof.chainId, + proof.blockNumber, + proof.blockHeader, + proof.ancestralBlockNumber, + proof.ancestralBlockHeaders, + shoyuBashi + ); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); + bytes32 stateRoot = bytes32(blockHeaderFields[3].toUint()); + (, , bytes32 storageHash, ) = verifyAccountProof(proof.account, stateRoot, proof.accountProof); + return verifyStorageProof(storageHash, proof.storageKeys, proof.storageProof); + } + + /** + * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. + * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. + * If it doesn't match directly, it will verify the block by traversing ancestral blocks until a matching block header or ancestor is found. + * If no match is found, it reverts with `BlockHeaderNotFound`. + * @param chainId The chain ID associated with the block. + * @param blockNumber The number of the block to be checked. + * @param blockHeader The RLP-encoded header of the block. + * @param ancestralBlockNumber The block number of the ancestral block to be verified, if applicable. + * @param ancestralBlockHeaders An array of RLP-encoded headers for ancestral blocks. + * @param shoyuBashi The address of ShoyuBashi contract. + * @return bytes The RLP-encoded block header if successfully verified. + */ + function checkBlockHeaderAgainstHashi( + uint256 chainId, + uint256 blockNumber, + bytes memory blockHeader, + uint256 ancestralBlockNumber, + bytes[] memory ancestralBlockHeaders, + address shoyuBashi + ) internal view returns (bytes memory) { + bytes32 blockHeaderHash = keccak256(blockHeader); + bytes32 currentBlockHeaderHash = IShoyuBashi(shoyuBashi).getThresholdHash(chainId, blockNumber); + if (currentBlockHeaderHash == blockHeaderHash && ancestralBlockHeaders.length == 0) return blockHeader; + + for (uint256 i = 0; i < ancestralBlockHeaders.length; i++) { + RLPReader.RLPItem memory ancestralBlockHeaderRLP = RLPReader.toRlpItem(ancestralBlockHeaders[i]); + RLPReader.RLPItem[] memory ancestralBlockHeaderContent = ancestralBlockHeaderRLP.toList(); + + bytes32 blockParentHash = bytes32(ancestralBlockHeaderContent[0].toUint()); + uint256 currentAncestralBlockNumber = uint256(ancestralBlockHeaderContent[8].toUint()); + + bytes32 ancestralBlockHeaderHash = keccak256(ancestralBlockHeaders[i]); + if (ancestralBlockHeaderHash != currentBlockHeaderHash) + revert ConflictingBlockHeader( + currentAncestralBlockNumber, + ancestralBlockHeaderHash, + currentBlockHeaderHash + ); + + if (ancestralBlockNumber == currentAncestralBlockNumber) { + return ancestralBlockHeaders[i]; + } else { + currentBlockHeaderHash = blockParentHash; + } + } + + revert BlockHeaderNotFound(); + } + + /** + * @notice Extracts the fields of a transaction receipt from its RLP-encoded data. + * @dev This function handles different transaction types by setting the appropriate offset for RLP parsing. + * It adjusts the starting point based on the transaction type byte, then uses RLPReader to parse the fields. + * @param value The RLP-encoded transaction receipt. + * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. + */ + function extractReceiptFields(bytes memory value) internal pure returns (RLPReader.RLPItem[] memory) { + uint256 offset; + if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { + offset = 1; + } else if (value[0] >= 0xc0) { + offset = 0; + } else { + revert UnsupportedTxType(); + } + + uint256 memPtr; + assembly { + memPtr := add(value, add(0x20, mul(0x01, offset))) + } + + return RLPReader.RLPItem(value.length - offset, memPtr).toList(); + } + + /** + * @notice Verifies an account proof and extracts account fields from it. + * @dev This function uses a Merkle proof to verify the account state in a given state root. + * It retrieves and decodes the account data, checking the storage root and account structure. + * @param account The address of the account to verify. + * @param stateRoot The state root against which the account proof is verified. + * @param proof A Merkle proof required to verify the account. + * @return uint256 The nonce of the account. + * @return uint256 The balance of the account. + * @return bytes32 The storage root of the account. + * @return bytes32 The code hash of the account. + */ + function verifyAccountProof( + address account, + bytes32 stateRoot, + bytes[] memory proof + ) internal pure returns (uint256, uint256, bytes32, bytes32) { + bytes memory accountRlp = SecureMerkleTrie.get(abi.encodePacked(account), proof, stateRoot); + + bytes32 accountStorageRoot = bytes32(accountRlp.toRlpItem().toList()[2].toUint()); + if (accountStorageRoot.length == 0) revert InvalidStorageHash(); + RLPReader.RLPItem[] memory accountFields = accountRlp.toRlpItem().toList(); + if (accountFields.length != 4) revert InvalidAccount(); + // [nonce, balance, storageHash, codeHash] + return ( + accountFields[0].toUint(), + accountFields[1].toUint(), + bytes32(accountFields[2].toUint()), + bytes32(accountFields[3].toUint()) + ); + } + + /** + * @notice Verifies multiple storage proofs and retrieves the storage values associated with given keys. + * @dev This function iterates over provided storage keys and their respective proofs, + * using a Merkle proof to verify each storage value against the specified storage hash. + * @param storageHash The root hash of the storage trie for the account being verified. + * @param storageKeys An array of storage keys for which values need to be verified. + * @param proof A 2D array of Merkle proof elements for each storage key. + * @return bytes[] An array of storage values corresponding to each storage key. + */ + function verifyStorageProof( + bytes32 storageHash, + bytes32[] memory storageKeys, + bytes[][] memory proof + ) internal pure returns (bytes[] memory) { + bytes[] memory results = new bytes[](proof.length); + if (storageKeys.length == 0 || proof.length == 0 || storageKeys.length != proof.length) + revert InvalidStorageProofParams(); + for (uint256 i = 0; i < proof.length; ) { + RLPReader.RLPItem memory item = RLPReader.toRlpItem( + SecureMerkleTrie.get(abi.encode(storageKeys[i]), proof[i], storageHash) + ); + results[i] = item.toBytes(); + unchecked { + ++i; + } + } + return results; + } +} diff --git a/packages/evm/contracts/prover/HashiProverStructs.sol b/packages/evm/contracts/prover/HashiProverStructs.sol new file mode 100644 index 00000000..1257d335 --- /dev/null +++ b/packages/evm/contracts/prover/HashiProverStructs.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.0; + +/** + * @notice Represents a proof structure for verifying both account and storage data within a specific blockchain state. + * @dev This struct includes all necessary components to verify account existence and storage values in a specified block. + */ +struct AccountAndStorageProof { + uint256 chainId; // The ID of the blockchain where the proof is applicable. + uint256 blockNumber; // The block number at which the proof is generated. + bytes blockHeader; // The RLP-encoded header of the block containing the account state. + uint256 ancestralBlockNumber; // The block number of an ancestral block if needed for verification. + bytes[] ancestralBlockHeaders; // An array of RLP-encoded headers for ancestral blocks (used if the proof requires it). + address account; // The address of the account being proven. + bytes[] accountProof; // Merkle proof for verifying the account's state in the specified block. + bytes32[] storageKeys; // An array of storage keys for which values are being proven. + bytes[][] storageProof; // A 2D array of Merkle proofs for each storage key, verifying each key-value pair in the storage trie. +} + +struct ReceiptProof { + uint256 chainId; + uint256 blockNumber; + bytes blockHeader; + uint256 ancestralBlockNumber; + bytes[] ancestralBlockHeaders; + bytes[] receiptProof; + bytes transactionIndex; + uint256 logIndex; +} diff --git a/packages/evm/contracts/prover/HashiProverUpgradeable.sol b/packages/evm/contracts/prover/HashiProverUpgradeable.sol index 4441a14e..9ab2ede9 100644 --- a/packages/evm/contracts/prover/HashiProverUpgradeable.sol +++ b/packages/evm/contracts/prover/HashiProverUpgradeable.sol @@ -3,16 +3,10 @@ pragma solidity ^0.8.0; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; -import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; -import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol"; -import { IHashiProver } from "../interfaces/IHashiProver.sol"; -import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; - -contract HashiProverUpgradeable is IHashiProver, Initializable, OwnableUpgradeable { - using RLPReader for RLPReader.RLPItem; - using RLPReader for bytes; +import { HashiProverLib } from "./HashiProverLib.sol"; +import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +contract HashiProverUpgradeable is Initializable, OwnableUpgradeable { /// @notice Stores the address of the ShoyuBashi contract. /// @dev This address can be updated by the owner using the `setShoyuBashi` function. address public shoyuBashi; @@ -55,23 +49,7 @@ contract HashiProverUpgradeable is IHashiProver, Initializable, OwnableUpgradeab * @return bytes The RLP-encoded event corresponding to the specified `logIndex`. */ function verifyForeignEvent(ReceiptProof calldata proof) internal view returns (bytes memory) { - bytes memory blockHeader = _checkBlockHeaderAgainstHashi( - proof.chainId, - proof.blockNumber, - proof.blockHeader, - proof.ancestralBlockNumber, - proof.ancestralBlockHeaders - ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 receiptsRoot = bytes32(blockHeaderFields[5].toUint()); - - bytes memory value = MerkleTrie.get(proof.transactionIndex, proof.receiptProof, receiptsRoot); - RLPReader.RLPItem[] memory receiptFields = _extractReceiptFields(value); - if (receiptFields.length != 4) revert InvalidReceipt(); - - RLPReader.RLPItem[] memory logs = receiptFields[3].toList(); - if (proof.logIndex >= logs.length) revert InvalidLogIndex(); - return logs[proof.logIndex].toRlpBytes(); + return HashiProverLib.verifyForeignEvent(proof, shoyuBashi); } /** @@ -92,152 +70,7 @@ contract HashiProverUpgradeable is IHashiProver, Initializable, OwnableUpgradeab * @return bytes[] An array of storage values corresponding to the specified `storageKeys`. */ function verifyForeignStorage(AccountAndStorageProof calldata proof) internal view returns (bytes[] memory) { - bytes memory blockHeader = _checkBlockHeaderAgainstHashi( - proof.chainId, - proof.blockNumber, - proof.blockHeader, - proof.ancestralBlockNumber, - proof.ancestralBlockHeaders - ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 stateRoot = bytes32(blockHeaderFields[3].toUint()); - (, , bytes32 expectedStorageHash, ) = _verifyAccountProof(proof.account, stateRoot, proof.accountProof); - if (proof.storageHash != expectedStorageHash) revert InvalidStorageHash(); - return _verifyStorageProof(proof.storageHash, proof.storageKeys, proof.storageProof); - } - - /** - * @notice Verifies a block header against the Hashi contract by checking its hash and, if needed, traversing ancestral blocks. - * @dev This function first checks if the provided block header hash matches the threshold hash stored in the ShoyuBashi contract. - * If it doesn't match directly, it will verify the block by traversing ancestral blocks until a matching block header or ancestor is found. - * If no match is found, it reverts with `BlockHeaderNotFound`. - * @param chainId The chain ID associated with the block. - * @param blockNumber The number of the block to be checked. - * @param blockHeader The RLP-encoded header of the block. - * @param ancestralBlockNumber The block number of the ancestral block to be verified, if applicable. - * @param ancestralBlockHeaders An array of RLP-encoded headers for ancestral blocks. - * @return bytes The RLP-encoded block header if successfully verified. - */ - function _checkBlockHeaderAgainstHashi( - uint256 chainId, - uint256 blockNumber, - bytes memory blockHeader, - uint256 ancestralBlockNumber, - bytes[] memory ancestralBlockHeaders - ) private view returns (bytes memory) { - bytes32 blockHeaderHash = keccak256(blockHeader); - bytes32 currentBlockHeaderHash = IShoyuBashi(shoyuBashi).getThresholdHash(chainId, blockNumber); - if (currentBlockHeaderHash == blockHeaderHash && ancestralBlockHeaders.length == 0) return blockHeader; - - for (uint256 i = 0; i < ancestralBlockHeaders.length; i++) { - RLPReader.RLPItem memory ancestralBlockHeaderRLP = RLPReader.toRlpItem(ancestralBlockHeaders[i]); - RLPReader.RLPItem[] memory ancestralBlockHeaderContent = ancestralBlockHeaderRLP.toList(); - - bytes32 blockParentHash = bytes32(ancestralBlockHeaderContent[0].toUint()); - uint256 currentAncestralBlockNumber = uint256(ancestralBlockHeaderContent[8].toUint()); - - bytes32 ancestralBlockHeaderHash = keccak256(ancestralBlockHeaders[i]); - if (ancestralBlockHeaderHash != currentBlockHeaderHash) - revert ConflictingBlockHeader( - currentAncestralBlockNumber, - ancestralBlockHeaderHash, - currentBlockHeaderHash - ); - - if (ancestralBlockNumber == currentAncestralBlockNumber) { - return ancestralBlockHeaders[i]; - } else { - currentBlockHeaderHash = blockParentHash; - } - } - - revert BlockHeaderNotFound(); - } - - /** - * @notice Extracts the fields of a transaction receipt from its RLP-encoded data. - * @dev This function handles different transaction types by setting the appropriate offset for RLP parsing. - * It adjusts the starting point based on the transaction type byte, then uses RLPReader to parse the fields. - * @param value The RLP-encoded transaction receipt. - * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. - */ - function _extractReceiptFields(bytes memory value) private pure returns (RLPReader.RLPItem[] memory) { - uint256 offset; - if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { - offset = 1; - } else if (value[0] >= 0xc0) { - offset = 0; - } else { - revert UnsupportedTxType(); - } - - uint256 memPtr; - assembly { - memPtr := add(value, add(0x20, mul(0x01, offset))) - } - - return RLPReader.RLPItem(value.length - offset, memPtr).toList(); - } - - /** - * @notice Verifies an account proof and extracts account fields from it. - * @dev This function uses a Merkle proof to verify the account state in a given state root. - * It retrieves and decodes the account data, checking the storage root and account structure. - * @param account The address of the account to verify. - * @param stateRoot The state root against which the account proof is verified. - * @param proof A Merkle proof required to verify the account. - * @return uint256 The nonce of the account. - * @return uint256 The balance of the account. - * @return bytes32 The storage root of the account. - * @return bytes32 The code hash of the account. - */ - function _verifyAccountProof( - address account, - bytes32 stateRoot, - bytes[] memory proof - ) private pure returns (uint256, uint256, bytes32, bytes32) { - bytes memory accountRlp = SecureMerkleTrie.get(abi.encodePacked(account), proof, stateRoot); - - bytes32 accountStorageRoot = bytes32(accountRlp.toRlpItem().toList()[2].toUint()); - if (accountStorageRoot.length == 0) revert InvalidStorageHash(); - RLPReader.RLPItem[] memory accountFields = accountRlp.toRlpItem().toList(); - if (accountFields.length != 4) revert InvalidAccount(); - // [nonce, balance, storageHash, codeHash] - return ( - accountFields[0].toUint(), - accountFields[1].toUint(), - bytes32(accountFields[2].toUint()), - bytes32(accountFields[3].toUint()) - ); - } - - /** - * @notice Verifies multiple storage proofs and retrieves the storage values associated with given keys. - * @dev This function iterates over provided storage keys and their respective proofs, - * using a Merkle proof to verify each storage value against the specified storage hash. - * @param storageHash The root hash of the storage trie for the account being verified. - * @param storageKeys An array of storage keys for which values need to be verified. - * @param proof A 2D array of Merkle proof elements for each storage key. - * @return bytes[] An array of storage values corresponding to each storage key. - */ - function _verifyStorageProof( - bytes32 storageHash, - bytes32[] memory storageKeys, - bytes[][] memory proof - ) private pure returns (bytes[] memory) { - bytes[] memory results = new bytes[](proof.length); - if (storageKeys.length == 0 || proof.length == 0 || storageKeys.length != proof.length) - revert InvalidStorageProofParams(); - for (uint256 i = 0; i < proof.length; ) { - RLPReader.RLPItem memory item = RLPReader.toRlpItem( - SecureMerkleTrie.get(abi.encode(storageKeys[i]), proof[i], storageHash) - ); - results[i] = item.toBytes(); - unchecked { - ++i; - } - } - return results; + return HashiProverLib.verifyForeignStorage(proof, shoyuBashi); } /// @notice This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain (see [OpenZeppelin's guide about storage gaps](https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps)). diff --git a/packages/evm/contracts/test/HashiProverTest.sol b/packages/evm/contracts/test/HashiProverTest.sol index dc3c4383..295b2121 100644 --- a/packages/evm/contracts/test/HashiProverTest.sol +++ b/packages/evm/contracts/test/HashiProverTest.sol @@ -2,15 +2,16 @@ pragma solidity ^0.8.20; import { HashiProver } from "../prover/HashiProver.sol"; +import "../prover/HashiProverStructs.sol"; contract HashiProverTest is HashiProver { constructor(address shoyuBashi) HashiProver(shoyuBashi) {} - function getStorageValue(HashiProver.AccountAndStorageProof calldata proof) external view returns (bytes[] memory) { + function getStorageValue(AccountAndStorageProof calldata proof) external view returns (bytes[] memory) { return verifyForeignStorage(proof); } - function getEventValues(HashiProver.ReceiptProof calldata proof) external view returns (bytes memory) { + function getEventValues(ReceiptProof calldata proof) external view returns (bytes memory) { return verifyForeignEvent(proof); } } diff --git a/packages/evm/contracts/test/HashiProverTestUpgradeable.sol b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol index d213f450..440772e5 100644 --- a/packages/evm/contracts/test/HashiProverTestUpgradeable.sol +++ b/packages/evm/contracts/test/HashiProverTestUpgradeable.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.20; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { HashiProverUpgradeable } from "../prover/HashiProverUpgradeable.sol"; +import "../prover/HashiProverStructs.sol"; contract HashiProverTestUpgradeable is UUPSUpgradeable, HashiProverUpgradeable { function initialize(address shoyuBashi) public initializer { @@ -10,13 +11,11 @@ contract HashiProverTestUpgradeable is UUPSUpgradeable, HashiProverUpgradeable { __HashiProverUpgradeable_init(shoyuBashi); } - function getStorageValue( - HashiProverUpgradeable.AccountAndStorageProof calldata proof - ) external view returns (bytes[] memory) { + function getStorageValue(AccountAndStorageProof calldata proof) external view returns (bytes[] memory) { return verifyForeignStorage(proof); } - function getEventValues(HashiProverUpgradeable.ReceiptProof calldata proof) external view returns (bytes memory) { + function getEventValues(ReceiptProof calldata proof) external view returns (bytes memory) { return verifyForeignEvent(proof); } From 7bca27e2465ecfffd747bba01f538943a7281f47 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 12 Nov 2024 14:33:27 +0100 Subject: [PATCH 3/5] refactor(rpc): rm storageHash from proof returned by hashi_getAccountAndStorageProof --- packages/evm/test/05_HashiProver.spec.ts | 2 +- packages/evm/test/proofs.ts | 2 -- packages/rpc/src/methods/get-account-and-storage-proof.ts | 1 - packages/rpc/src/types/index.ts | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/evm/test/05_HashiProver.spec.ts b/packages/evm/test/05_HashiProver.spec.ts index 92f324c3..02efc252 100644 --- a/packages/evm/test/05_HashiProver.spec.ts +++ b/packages/evm/test/05_HashiProver.spec.ts @@ -82,7 +82,7 @@ describe("HashiProver", () => { ["0xf72ab984efa166b226dcb589bc445afeb8e666f789173a32de6d04108ac5cb8c"], ) const wrongProof = [...ACCOUNT_AND_STORAGE_PROOF] - wrongProof[9] = [ + wrongProof[8] = [ [ "0xf90211a01922b5f82f07bee421217744ed6d4e95b98852241f24dffa2f5701b1ddb8e6dca03fec17456b28fe0aea41291618b766813d90061104d8731e6e937b0922cae1f6a0fb94b76b2f2c5d4b40890a18b9f0579966eb56274035a58010db113ccbab922fa085b2e52483d7a1448504098bd8b3a0fc68becfe6fcf5e8f7442d08d1c17d9446a0c8b2aa37759feac9aad765fca7545ab9d02015364261d3f35384154e77ef77e9a0bc48fb8581b0926eb1d707cb1668b5ecdf2b1759fb7ed8d440bf1163103bd810a046fe65e822efc9f1b49e43ed4eb7600e9658c306b70a95999aeb0112c9954f9ca03d66c408b9ced8ee40c6281f15e26bb7db314045d5f65322fc1d5e24544b9192a0b26bf58b679aaf2a0a5f5a7fc9507e856f31e01a7ea47d9c5719957e51d99f92a003555409bff0cbb217e5d9fbd7d9e3b46a451e2b3cc0f27b34a3b553634770f7a05f71f83b940082edb3f0afaedd000ae4789a8b459c0befecf0085308961a38f4a0110aca3b49ff8a7fc3d60295d0c18602e576427a02907986d3fcdec5c8406607a0b197a531e48bf6f203d6f8b4088117caaa55d2318177d00a849c9bb9c0be11b5a021c55c465168ceb84725b61988c7c174880c9bccb99510ebffcf715f01344022a0173421253267ac8dacdd78bb3a49e4e68ce44c987335e7e22e2067f5998ccc8ba0ddb9469be4af0c764ae2984533a34b6ac6ad4535a7bf773d1bdcaba414288d4e80", "0xf90211a0134f748fc5e8562c4037bb335c253e159c2d3c7a1dc48b1e006fee1ffcc63874a0dcad9ec65f0b0b3e3d265b468ceda4c2626bea957ba6dd0f25e91d8f43615dcba0b8fdad766b78548db43d60da964d1abdd784ae56bd9ad9dd5ce7911beadab941a01db88587d7758f452204d265122d451f416f29219de91d8f1fd98b4695ad56f8a06464403607b9759cf6cb0e1bdd58d3a231ece185267c59d0113836bbce312007a0a23247953c05226318750e90668afd8b8f4a308f1f3e5573f92c03cd4fa9cc99a0ec186ad6ea36e64969fac78982f9ddd2c78f01fb5f059afc8d9253cafb348272a00e259709d156973caac69a52dbde1569f0ea9fc58cc9333b6fff01bed4ced9c3a01f76d216b1d1f75ebdcece38a62dc6d85cf090cec0b17ea8fe4a2fbadf02e418a0a44e06aa48e8e2b81b82ac7a55d10e0e75fb0016475f40b4b2b199016fefef11a04e31f7d98493c4af332a55a088d75bd53a55d37feee0fb4ea4bb89bd6cf1189da01fe39db746e4eef3572d1863d2edf73ef178986a33929a353e30d5a5459cffb7a0c64a8a52d3dfb4c33e5eac53820c25604e4c8f34062e2f31a00ada4c4e8ac794a02b09776c323c5f8fc6b69732fc17e7ac78fb63c9a42243b5b65bb067b05af034a0c371630f7af67645f11a19b70a01e20284fd2c3afa8ad5e72fa939e775090b94a0a2680edf63d1735ee9ce81c2bb867aa6708db5be648b511b2997cf6a82b7b12a80", diff --git a/packages/evm/test/proofs.ts b/packages/evm/test/proofs.ts index 90481fa2..1a6cfec7 100644 --- a/packages/evm/test/proofs.ts +++ b/packages/evm/test/proofs.ts @@ -15,7 +15,6 @@ export const ACCOUNT_AND_STORAGE_PROOF = [ "0xf9011180a0af3e6c1703878fa0f54ce9ef81044131303255beda112c1750bd46e46c17749780808080a0ee3ef4e754b7044fbaf982f80b8ab4ea00503fe3ec4c50fd7864e81ce1e6c4408080a075fb4f68ac224ec54d38eee3bd972654ca5ee1833530f0ebefd71a9f49cf09f1a05c099f09257a656d98101ccd60d3fbe861cb889f9699b8eed136268028021b70a0b90a5365f3205e9df1129eecaa73667c4d2c567f1ab45f63860c3671b46dc27780a0e38b7963499d1bbde43a95289356e98e19cdc1e21e10e097e1490f15e3662e0ba052b569b11cc62b342b35edfd24e3f8c4f9b3ec16930ac8986eefe14e609d073ba052fe3bf973b9ff06f119a91481e15215c3eccadc584ce8b6e7a05ea68c73054180", "0xf8669d3d676334b26bbb561def1bb646db346a0ea5f7c4f069e5ce4083818685b846f8440180a0b8f3308b625ddb7bce9e10a6a13d9988d1b865eb09df34844bf6b86b00904ae6a0aad43333d28e146557f1c682e8a4226743fb231fdd00a577512233bd9e920008", ], - "0xb8f3308b625ddb7bce9e10a6a13d9988d1b865eb09df34844bf6b86b00904ae6", ["0x000000000000000000000000000000000000000000000000000000000000000b"], [ [ @@ -51,7 +50,6 @@ export const ACCOUNT_AND_STORAGE_PROOF_WITH_ANCESTRAL_BLOCKS = [ "0xf9011180a0af3e6c1703878fa0f54ce9ef81044131303255beda112c1750bd46e46c17749780808080a0ee3ef4e754b7044fbaf982f80b8ab4ea00503fe3ec4c50fd7864e81ce1e6c4408080a075fb4f68ac224ec54d38eee3bd972654ca5ee1833530f0ebefd71a9f49cf09f1a05c099f09257a656d98101ccd60d3fbe861cb889f9699b8eed136268028021b70a0b90a5365f3205e9df1129eecaa73667c4d2c567f1ab45f63860c3671b46dc27780a0e38b7963499d1bbde43a95289356e98e19cdc1e21e10e097e1490f15e3662e0ba0ce536ccc69891fc11f58ebaa1a9f09bd1644af223c17493de3fa30e6e39f6845a052fe3bf973b9ff06f119a91481e15215c3eccadc584ce8b6e7a05ea68c73054180", "0xf8669d3d676334b26bbb561def1bb646db346a0ea5f7c4f069e5ce4083818685b846f8440180a011a7fd82551848c90631f70de7f85bbc1fb9cce3618351c58eef7d86c6e6535da0aad43333d28e146557f1c682e8a4226743fb231fdd00a577512233bd9e920008", ], - "0x11a7fd82551848c90631f70de7f85bbc1fb9cce3618351c58eef7d86c6e6535d", ["0x000000000000000000000000000000000000000000000000000000000000000b"], [ [ diff --git a/packages/rpc/src/methods/get-account-and-storage-proof.ts b/packages/rpc/src/methods/get-account-and-storage-proof.ts index 186646bb..b30b5435 100644 --- a/packages/rpc/src/methods/get-account-and-storage-proof.ts +++ b/packages/rpc/src/methods/get-account-and-storage-proof.ts @@ -54,7 +54,6 @@ const getAccountAndStorageProof = async ({ ancestralBlockHeaders, address, proof.accountProof, - proof.storageHash, proof.storageProof.map(({ key }: any) => key), proof.storageProof.map(({ proof: storageProof }: any) => storageProof), ], diff --git a/packages/rpc/src/types/index.ts b/packages/rpc/src/types/index.ts index 0113e3b6..8283f9c3 100644 --- a/packages/rpc/src/types/index.ts +++ b/packages/rpc/src/types/index.ts @@ -6,7 +6,6 @@ export type AccountAndStorageProof = [ `0x${string}`[], `0x${string}`, `0x${string}`, - `0x${string}`, `0x${string}`[], `0x${string}`, ] From a51ce8b65cf7ad71e6c91891430a1608dd1d0a22 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Tue, 12 Nov 2024 19:20:15 +0100 Subject: [PATCH 4/5] refactor(evm): replaces solidity-rlp with rlp from @eth-optimism within HashiProverLib --- .../evm/contracts/prover/HashiProverLib.sol | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/packages/evm/contracts/prover/HashiProverLib.sol b/packages/evm/contracts/prover/HashiProverLib.sol index a60222cf..e3945916 100644 --- a/packages/evm/contracts/prover/HashiProverLib.sol +++ b/packages/evm/contracts/prover/HashiProverLib.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.0; import { SecureMerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/SecureMerkleTrie.sol"; import { MerkleTrie } from "@eth-optimism/contracts-bedrock/src/libraries/trie/MerkleTrie.sol"; -import { RLPReader } from "solidity-rlp/contracts/RLPReader.sol"; -import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; +import { RLPReader } from "@eth-optimism/contracts-bedrock/src/libraries/rlp/RLPReader.sol"; import { AccountAndStorageProof, ReceiptProof } from "./HashiProverStructs.sol"; +import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol"; library HashiProverLib { using RLPReader for RLPReader.RLPItem; @@ -45,16 +45,16 @@ library HashiProverLib { proof.ancestralBlockHeaders, shoyuBashi ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 receiptsRoot = bytes32(blockHeaderFields[5].toUint()); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRLPItem().readList(); + bytes32 receiptsRoot = bytes32(blockHeaderFields[5].readBytes()); bytes memory value = MerkleTrie.get(proof.transactionIndex, proof.receiptProof, receiptsRoot); RLPReader.RLPItem[] memory receiptFields = extractReceiptFields(value); if (receiptFields.length != 4) revert InvalidReceipt(); - RLPReader.RLPItem[] memory logs = receiptFields[3].toList(); + RLPReader.RLPItem[] memory logs = receiptFields[3].readList(); if (proof.logIndex >= logs.length) revert InvalidLogIndex(); - return logs[proof.logIndex].toRlpBytes(); + return logs[proof.logIndex].readRawBytes(); } /** @@ -86,8 +86,8 @@ library HashiProverLib { proof.ancestralBlockHeaders, shoyuBashi ); - RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRlpItem().toList(); - bytes32 stateRoot = bytes32(blockHeaderFields[3].toUint()); + RLPReader.RLPItem[] memory blockHeaderFields = blockHeader.toRLPItem().readList(); + bytes32 stateRoot = bytes32(blockHeaderFields[3].readBytes()); (, , bytes32 storageHash, ) = verifyAccountProof(proof.account, stateRoot, proof.accountProof); return verifyStorageProof(storageHash, proof.storageKeys, proof.storageProof); } @@ -118,11 +118,10 @@ library HashiProverLib { if (currentBlockHeaderHash == blockHeaderHash && ancestralBlockHeaders.length == 0) return blockHeader; for (uint256 i = 0; i < ancestralBlockHeaders.length; i++) { - RLPReader.RLPItem memory ancestralBlockHeaderRLP = RLPReader.toRlpItem(ancestralBlockHeaders[i]); - RLPReader.RLPItem[] memory ancestralBlockHeaderContent = ancestralBlockHeaderRLP.toList(); + RLPReader.RLPItem[] memory ancestralBlockHeaderFields = ancestralBlockHeaders[i].readList(); - bytes32 blockParentHash = bytes32(ancestralBlockHeaderContent[0].toUint()); - uint256 currentAncestralBlockNumber = uint256(ancestralBlockHeaderContent[8].toUint()); + bytes32 blockParentHash = bytes32(ancestralBlockHeaderFields[0].readBytes()); + uint256 currentAncestralBlockNumber = bytesToUint(ancestralBlockHeaderFields[8].readBytes()); bytes32 ancestralBlockHeaderHash = keccak256(ancestralBlockHeaders[i]); if (ancestralBlockHeaderHash != currentBlockHeaderHash) @@ -150,21 +149,31 @@ library HashiProverLib { * @return RLPReader.RLPItem[] An array of RLP items representing the fields of the receipt. */ function extractReceiptFields(bytes memory value) internal pure returns (RLPReader.RLPItem[] memory) { + bytes1 txTypeOrFirstByte = value[0]; + uint256 offset; - if (value[0] == 0x01 || value[0] == 0x02 || value[0] == 0x03 || value[0] == 0x7e) { + if ( + txTypeOrFirstByte == 0x01 || + txTypeOrFirstByte == 0x02 || + txTypeOrFirstByte == 0x03 || + txTypeOrFirstByte == 0x7e // EIP-2718 (https://eips.ethereum.org/EIPS/eip-2718) transaction + ) { offset = 1; - } else if (value[0] >= 0xc0) { + } else if (txTypeOrFirstByte >= 0xc0) { offset = 0; } else { revert UnsupportedTxType(); } - uint256 memPtr; + uint256 ptr; assembly { - memPtr := add(value, add(0x20, mul(0x01, offset))) + ptr := add(value, 32) } - return RLPReader.RLPItem(value.length - offset, memPtr).toList(); + return + RLPReader + .RLPItem({ length: value.length - offset, ptr: RLPReader.MemoryPointer.wrap(ptr + offset) }) + .readList(); } /** @@ -186,16 +195,16 @@ library HashiProverLib { ) internal pure returns (uint256, uint256, bytes32, bytes32) { bytes memory accountRlp = SecureMerkleTrie.get(abi.encodePacked(account), proof, stateRoot); - bytes32 accountStorageRoot = bytes32(accountRlp.toRlpItem().toList()[2].toUint()); + bytes32 accountStorageRoot = bytes32(accountRlp.toRLPItem().readList()[2].readBytes()); if (accountStorageRoot.length == 0) revert InvalidStorageHash(); - RLPReader.RLPItem[] memory accountFields = accountRlp.toRlpItem().toList(); + RLPReader.RLPItem[] memory accountFields = accountRlp.toRLPItem().readList(); if (accountFields.length != 4) revert InvalidAccount(); // [nonce, balance, storageHash, codeHash] return ( - accountFields[0].toUint(), - accountFields[1].toUint(), - bytes32(accountFields[2].toUint()), - bytes32(accountFields[3].toUint()) + bytesToUint(accountFields[0].readBytes()), + bytesToUint(accountFields[1].readBytes()), + bytes32(accountFields[2].readBytes()), + bytes32(accountFields[3].readBytes()) ); } @@ -217,14 +226,27 @@ library HashiProverLib { if (storageKeys.length == 0 || proof.length == 0 || storageKeys.length != proof.length) revert InvalidStorageProofParams(); for (uint256 i = 0; i < proof.length; ) { - RLPReader.RLPItem memory item = RLPReader.toRlpItem( + RLPReader.RLPItem memory item = RLPReader.toRLPItem( SecureMerkleTrie.get(abi.encode(storageKeys[i]), proof[i], storageHash) ); - results[i] = item.toBytes(); + results[i] = item.readBytes(); unchecked { ++i; } } return results; } + + /** + * @notice Converts a byte array to an unsigned integer (uint256). + * @param b The byte array to convert to an unsigned integer. + * @return uint256 The resulting unsigned integer from the byte array. + */ + function bytesToUint(bytes memory b) internal pure returns (uint256) { + uint256 number; + for (uint256 i = 0; i < b.length; i++) { + number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1)))); + } + return number; + } } From 36c8e469d1bdac7650d2ca288561c2ac05bf3c72 Mon Sep 17 00:00:00 2001 From: Alessandro Manfredi Date: Wed, 20 Nov 2024 18:47:53 +0100 Subject: [PATCH 5/5] refactor(evm): adds comments for ReceiptProof --- .../contracts/prover/HashiProverStructs.sol | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/evm/contracts/prover/HashiProverStructs.sol b/packages/evm/contracts/prover/HashiProverStructs.sol index 1257d335..3b0e7f78 100644 --- a/packages/evm/contracts/prover/HashiProverStructs.sol +++ b/packages/evm/contracts/prover/HashiProverStructs.sol @@ -17,13 +17,17 @@ struct AccountAndStorageProof { bytes[][] storageProof; // A 2D array of Merkle proofs for each storage key, verifying each key-value pair in the storage trie. } +/** + * @notice Represents a proof structure for verifying a transaction receipt and its corresponding log entry within a specific block. + * @dev This struct includes all necessary components to verify the validity of a transaction receipt and the log it produced in a specified block. + */ struct ReceiptProof { - uint256 chainId; - uint256 blockNumber; - bytes blockHeader; - uint256 ancestralBlockNumber; - bytes[] ancestralBlockHeaders; - bytes[] receiptProof; - bytes transactionIndex; - uint256 logIndex; + uint256 chainId; // The ID of the blockchain where the proof is applicable. + uint256 blockNumber; // The block number at which the transaction receipt is included. + bytes blockHeader; // The RLP-encoded header of the block containing the transaction receipt. + uint256 ancestralBlockNumber; // The block number of an ancestral block, if needed for receipt verification. + bytes[] ancestralBlockHeaders; // An array of RLP-encoded headers for ancestral blocks (used if the proof requires them). + bytes[] receiptProof; // Merkle proof for verifying the transaction receipt in the block's receipt trie. + bytes transactionIndex; // The index of the transaction within the block's transaction list (RLP-encoded). + uint256 logIndex; // The index of the log entry within the transaction receipt being proven. }