diff --git a/hardhat.config.ts b/hardhat.config.ts index f585ada2..6bf479e3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,6 +1,7 @@ import "module-alias/register"; import "@nomicfoundation/hardhat-chai-matchers"; +import "@nomiclabs/hardhat-ethers"; import "@nomiclabs/hardhat-etherscan"; import "@openzeppelin/hardhat-upgrades"; import "@typechain/hardhat"; diff --git a/hardhat.config.zksync.ts b/hardhat.config.zksync.ts index 904d53f1..8cc09cde 100644 --- a/hardhat.config.zksync.ts +++ b/hardhat.config.zksync.ts @@ -4,6 +4,7 @@ import "@matterlabs/hardhat-zksync"; import "@matterlabs/hardhat-zksync-solc"; import "@matterlabs/hardhat-zksync-verify"; import "@nomicfoundation/hardhat-chai-matchers"; +import "@nomiclabs/hardhat-ethers"; import "hardhat-dependency-compiler"; import "hardhat-deploy"; import { HardhatUserConfig, task } from "hardhat/config"; diff --git a/package.json b/package.json index 0bf23a0a..c764fc14 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.6", "@nomicfoundation/hardhat-toolbox": "^2.0.0", "@nomicfoundation/hardhat-verify": "^2.0.8", - "@nomiclabs/hardhat-ethers": "^2.2.1", + "@nomiclabs/hardhat-ethers": "^2.2.3", "@nomiclabs/hardhat-etherscan": "^3.1.2", "@openzeppelin/contracts": "^4.8.2", "@openzeppelin/contracts-upgradeable": "^4.8.2", @@ -77,6 +77,7 @@ "@types/chai": "^4.3.4", "@types/debug": "^4.1.12", "@types/fs-extra": "^9.0.13", + "@types/json-stable-stringify": "^1.0.36", "@types/mocha": "^10.0.0", "@types/node": "^18.16.3", "@typescript-eslint/eslint-plugin": "^5.44.0", @@ -98,6 +99,7 @@ "hardhat-docgen": "^1.3.0", "hardhat-gas-reporter": "^1.0.9", "husky": "^8.0.3", + "json-stable-stringify": "^1.1.1", "lint-staged": "^13.0.4", "lodash": "^4.17.21", "mocha": "^10.1.0", diff --git a/script/generateProofs.ts b/script/generateProofs.ts new file mode 100644 index 00000000..c515813d --- /dev/null +++ b/script/generateProofs.ts @@ -0,0 +1,175 @@ +import "dotenv/config"; +import { BigNumber, utils } from "ethers"; +import { hexStripZeros, hexZeroPad } from "ethers/lib/utils.js"; +import * as fs from "fs"; +import { network } from "hardhat"; +import stringify from "json-stable-stringify"; + +import { + formatToProofRLP, + getExtendedBlock, + getProof, + getSolidityStorageSlotBytes, + getSolidityTwoLevelStorageSlotHash, + prepareBLockRLP, +} from "./utils.ts"; + +export type ProofData = { + blockNumber?: number; + blockHash?: string; + accountStateProofRLP?: string; + blockHeaderRLP?: string; + xvsVaultAddress?: string; + checkpointsSlot?: string; + numCheckpointsSlot?: string; + checkpointsSlotHash?: string; + numCheckpointsSlotHash?: string; + numCheckpoints?: number; + xvsVaultNumCheckpointsStorageProofRlp?: string; + checkpoint?: { + fromBlockNumber?: string; + votes?: string; + }; + xvsVaultCheckpointsStorageProofRlp?: string; +}; + +const xvsVault = { + sepolia: "0x1129f882eAa912aE6D4f6D445b2E2b1eCbA99fd5", + ethereum: "0xA0882C2D5DF29233A092d2887A258C2b90e9b994", + opbnbtestnet: "0xB14A0e72C5C202139F78963C9e89252c1ad16f01", + opbnbmainnet: "0x7dc969122450749A8B0777c0e324522d67737988", + arbitrumone: "0x8b79692AAB2822Be30a6382Eb04763A74752d5B4", + arbitrumsepolia: "0x407507DC2809D3aa31D54EcA3BEde5C5c4C8A17F", + zksyncsepolia: "0x825f9EE3b2b1C159a5444A111A70607f3918564e", + zksyncmainnet: "0xbbB3C88192a5B0DB759229BeF49DcD1f168F326F", + opsepolia: "0x4d344e48F02234E82D7D1dB84d0A4A18Aa43Dacc", + opmainnet: "0x133120607C018c949E91AE333785519F6d947e01", +}; + +const SLOTS = { + checkpoints: 16, + numCheckpoint: 17, +}; + +const saveJson = (stringifiedJson: string) => { + fs.writeFileSync(`./tests/Syncing-of-votes/${process.env.REMOTE_NETWORK}Proofs.json`, stringifiedJson); +}; + +export const getProofsJson = (): ProofData => { + try { + const file = fs.readFileSync(`./tests/Syncing-of-votes/${process.env.REMOTE_NETWORK}Proofs.json`); + return JSON.parse(file.toString()); + } catch (error) { + return {}; + } +}; + +const generateRoots = async (xvsVaultAddress: string, numCheckpointSlotRaw: number, checkpointSlotRaw: number) => { + const proofsJson = getProofsJson(); + + if (!proofsJson["xvsVaultAddress"]) { + proofsJson["xvsVaultAddress"] = xvsVaultAddress; + } + + // calculate blockHeaderRLP + const blockData = await getExtendedBlock(parseInt(process.env.BLOCK as string)); + const blockHeaderRLP = prepareBLockRLP(blockData); + proofsJson.blockHash = blockData.hash; + proofsJson.blockNumber = BigNumber.from(blockData.number).toNumber(); + proofsJson.blockHeaderRLP = blockHeaderRLP; + + // calculate slots + const slots: string[] = []; + + const checkpointSlot = hexZeroPad(utils.hexlify(checkpointSlotRaw), 32); + slots.push(checkpointSlot); + proofsJson.checkpointsSlot = checkpointSlot; + + const numCheckpointSlot = hexZeroPad(utils.hexlify(numCheckpointSlotRaw), 32); + slots.push(numCheckpointSlot); + proofsJson.numCheckpointsSlot = numCheckpointSlot; + + // get account state proof rlp + const rawAccountProofData = await getProof(xvsVaultAddress, slots, proofsJson.blockNumber); + const accountStateProofRLP = formatToProofRLP(rawAccountProofData.accountProof); + proofsJson.accountStateProofRLP = accountStateProofRLP; + saveJson(stringify(proofsJson)); +}; + +const generateProofsNumCheckpointsSlot = async (vault: string, rawSlot: number, voter: string) => { + const proofsJson = getProofsJson(); + const hexSlot = utils.hexlify(rawSlot); + const slot = getSolidityStorageSlotBytes(hexSlot, voter); + if (!proofsJson.blockNumber) { + throw new Error("blockNumber is not set"); + } + + const numCheckpointsHex = await network.provider.send("eth_getStorageAt", [ + vault, + slot, + hexStripZeros(utils.hexlify(proofsJson.blockNumber)), + ]); + + const numCheckpoints = BigNumber.from(numCheckpointsHex).toNumber(); + + const rawProofData = await getProof(vault, [slot], proofsJson.blockNumber); + + const storageProofRlp = formatToProofRLP(rawProofData.storageProof[0].proof); + proofsJson.numCheckpointsSlotHash = slot; + proofsJson.numCheckpoints = numCheckpoints; + proofsJson.xvsVaultNumCheckpointsStorageProofRlp = storageProofRlp; + + saveJson(stringify(proofsJson)); +}; + +const generateXvsVaultProofsByCheckpoint = async (vault: string, rawSlot: number, voter: string) => { + const hexSlot = utils.hexlify(rawSlot); + const proofsJson = getProofsJson(); + + if (!proofsJson.numCheckpoints) { + throw new Error("numCheckpoints is zero"); + } + + const slot = getSolidityTwoLevelStorageSlotHash(hexSlot, voter, proofsJson.numCheckpoints - 1); + + if (!proofsJson.blockNumber) { + throw new Error("blockNumber is not set"); + } + + const checkpointData = await network.provider.send("eth_getStorageAt", [ + vault, + slot, + hexStripZeros(utils.hexlify(proofsJson.blockNumber)), + ]); + + const fromBlockNumberHex = "0x" + checkpointData.slice(-8); + const votesHex = checkpointData.slice(0, -8); + const fromBlockNumber = BigNumber.from(fromBlockNumberHex).toString(); + const votes = BigNumber.from(votesHex).toString(); + + const rawProofData = await getProof(vault, [slot], proofsJson.blockNumber); + + const storageProofRlp = formatToProofRLP(rawProofData.storageProof[0].proof); + + proofsJson.checkpointsSlotHash = slot; + proofsJson.checkpoint = { + fromBlockNumber, + votes, + }; + proofsJson.xvsVaultCheckpointsStorageProofRlp = storageProofRlp; + saveJson(stringify(proofsJson)); +}; + +const generateJson = async () => { + const XVS_VAULT = xvsVault[process.env.REMOTE_NETWORK as string]; + + await generateRoots(XVS_VAULT, SLOTS.checkpoints, SLOTS.numCheckpoint); + + await generateProofsNumCheckpointsSlot(XVS_VAULT, SLOTS.numCheckpoint, process.env.VOTER as string); + + await generateXvsVaultProofsByCheckpoint(XVS_VAULT, SLOTS.checkpoints, process.env.VOTER as string); +}; + +(async () => { + await generateJson(); +})(); diff --git a/script/utils.ts b/script/utils.ts new file mode 100644 index 00000000..c2d8660e --- /dev/null +++ b/script/utils.ts @@ -0,0 +1,85 @@ +import { ethers, providers, utils } from "ethers"; +import { defaultAbiCoder, hexStripZeros, hexZeroPad, keccak256 } from "ethers/lib/utils.js"; + +const provider = new providers.StaticJsonRpcProvider(process.env[`ARCHIVE_NODE_${process.env.REMOTE_NETWORK}`]); + +const RLP = require("rlp"); + +export function formatToProofRLP(rawData) { + return ethers.utils.RLP.encode(rawData.map(d => ethers.utils.RLP.decode(d))); +} + +export const getProof = async (address: string, storageKeys: string[], blockNumber: number) => { + return await provider.send("eth_getProof", [address, storageKeys, hexStripZeros(utils.hexlify(blockNumber))]); +}; + +export const getExtendedBlock = async (blockNumber: number) => { + const blockNumber_ = blockNumber ? hexStripZeros(utils.hexlify(blockNumber)) : "latest"; + return provider.send("eth_getBlockByNumber", [blockNumber_, false]); +}; +export function prepareBLockRLP(rawBlock) { + const blockHeader = [ + rawBlock.parentHash, + rawBlock.sha3Uncles, + rawBlock.miner, + rawBlock.stateRoot, + rawBlock.transactionsRoot, + rawBlock.receiptsRoot, + rawBlock.logsBloom, + rawBlock.difficulty === "0x0" ? "0x" : rawBlock.difficulty, + rawBlock.number, + rawBlock.gasLimit === "0x0" ? "0x" : rawBlock.gasLimit, + rawBlock.gasUsed === "0x0" ? "0x" : rawBlock.gasUsed, + rawBlock.timestamp, + rawBlock.extraData, + rawBlock.mixHash, + rawBlock.nonce, + ]; + if (rawBlock.baseFeePerGas) { + blockHeader.push(rawBlock.baseFeePerGas === "0x0" ? "0x" : rawBlock.baseFeePerGas); + } + if (rawBlock.withdrawalsRoot) { + blockHeader.push(rawBlock.withdrawalsRoot); + } + if (rawBlock.blobGasUsed) { + blockHeader.push(rawBlock.blobGasUsed === "0x0" ? "0x" : rawBlock.blobGasUsed); + } + if (rawBlock.excessBlobGas) { + blockHeader.push(rawBlock.excessBlobGas === "0x0" ? "0x" : rawBlock.excessBlobGas); + } + if (rawBlock.parentBeaconBlockRoot) { + blockHeader.push(rawBlock.parentBeaconBlockRoot); + } + const encodedHeader = RLP.encode(blockHeader); + const encodedHeaderHex = "0x" + Buffer.from(encodedHeader).toString("hex"); + + return encodedHeaderHex; +} + +export function getSolidityStorageSlotBytes( + mappingSlot, //: BytesLike, + key, //: string +) { + const slot = hexZeroPad(mappingSlot, 32); + return hexStripZeros(keccak256(defaultAbiCoder.encode(["address", "uint256"], [key, slot]))); +} + +export function getSolidityTwoLevelStorageSlotHash( + rawSlot, // number + voter, // string + numCheckpoints, // number +) { + const abiCoder = new ethers.utils.AbiCoder(); + // ABI Encode the first level of the mapping + // abi.encode(address(voter), uint256(MAPPING_SLOT)) + // The keccak256 of this value will be the "slot" of the inner mapping + const firstLevelEncoded = abiCoder.encode(["address", "uint256"], [voter, ethers.BigNumber.from(rawSlot)]); + + // ABI Encode the second level of the mapping + // abi.encode(uint256(numCheckpoints)) + const secondLevelEncoded = abiCoder.encode(["uint256"], [ethers.BigNumber.from(numCheckpoints)]); + + // Compute the storage slot of [address][uint256] + // keccak256(abi.encode(uint256(numCheckpoints)) . abi.encode(address(voter), uint256(MAPPING_SLOT))) + return ethers.utils.keccak256(ethers.utils.concat([secondLevelEncoded, ethers.utils.keccak256(firstLevelEncoded)])); +} diff --git a/tests/Syncing-of-votes/sepoliaProofs.json b/tests/Syncing-of-votes/sepoliaProofs.json new file mode 100644 index 00000000..72bbb2fb --- /dev/null +++ b/tests/Syncing-of-votes/sepoliaProofs.json @@ -0,0 +1 @@ +{"accountStateProofRLP":"0xf90d66f90211a0bffd482e8cf690c90e7cad7998b35e09e24daac6e7c66f10b9f18e9c267b62a8a0fdbd043ff6c77ebe9a83890040e0194b294c8f82ae172d93745988d473ca0002a041482adccca0cdf5ff8ada6017b0eb8fc54d0d25fea1f7a6b4d33497256aea18a024ea31005ae5b2fb211a5a82e2904484a725a2dae7c455dbbbac7915fb7bf6a7a068f5a279a7f9fcf0b1247bcfdc29515e47b8ab12a81c2864c1d83db036d3cbfda0d762c1e70b0db4f40c131c7db6e8764dd1f7e0fbe59be35cf3f2e12cf69b7c9fa05e8bfa0e8c4391463c995679f0319e735f73ff3a92239324cfda93ecba8ff1e9a0684f281be3bb9d63dee6f0a3b85b2cce9f6bbebd936d97d3ec2f60fa4314f78ba02ff4108e6de5d8e445d5c324cce1ccbdc6197093fe92bf848f0ee4d4a97b64cda00070c4c28c3b15b9e6d1e7140b24dbbafe14f2912f02df48a2707c83712ac34aa0047bc6c91836ad024e886b2f81e106c382b14d3af71afdb09c1668da2b506d3ba0bf469e1788e762b0f34917bdfb3183d59733eb46868767544aa0c26d11cd9285a0778020d9f09ada2c8246e4802dcc81a9b57c8d082449e184ab116d8169813a60a07284a2482be2ae2e95372ac6f28b2783b1b36a91fea3ce540ea8d0ef7706724ea099ed9720a0f7a6cdb617717438afabc009114baaef7dc4eb14019f4f9ee4d770a0818aee63967096e292fad0a261893957f938e55cd3203a0343c1595d125e1d4080f90211a04f2006e6e3a934ad0dc8ee5a679619d36be8529445359b69006d27c4181bf158a06ecd13afe9631e04ff1bba0f6daa92fd49a13a0507c8da2eb01e3c862bc9fea1a04097a1e46d41c0556235422b1bcf4f40c7c5df958f29c5baf2097ff494d05995a09b3a61d9ee9bc6f40db87f7164ba48bf0422b68deedac2c3134d7c873d10b19ca0b957dc3effe9acc6a77cb8bc437f17908a534ced350898060ff33ca0fcebec95a018d25cd477a8052a12a96624b04069d86fcb1862a2ba09adfce3e0abe1cc426ba0293a07bb8be587c10de909c58aca184b3c95ee772babf75e53cba210d85659fca0ba51326c6c20db5e2139d60797cd3d30b0baef4c5da2adf431f06ec0f6c9fc90a03f84cab88a59fd85437bae600dbc817c74873773b74ea03c15f2c7c8718ce2afa023a553bd861f88211a248b19c5ff61a87e6b191d6148c27cde2e3cfdc3889fada0103059e7d1f39acc9ff52699a9a802289a90b8b7e5c0022e334a37a91dee5965a0fdc1baa338ec64528e2697628571103d4e4ead3d613942e07c0dc563fc0f6b7ca03232d0f9fbb6637b5671298c76adfa604125c6f494b6ac117d5eeb950c408424a0bfe86b828927d849b85c8a7c609fee646fc309f8bb67dcba011177c41aac271ca028c4fffb65a3f7f4151f4c3d5957d6b82b7a16a1a97cfb4be7af50e1abcdf60da029f4c2a52f266da2c56cfd6b030f0f23ed448fb245f03e99e897be648b84c78280f90211a05ce5f36e7b7bc7fc75f54078b2e1120b66d684c612528dc65b5b1e7005bd572ba02a5b98498cf71626740e17dfe5afb0a82ebc57c44c16b0e448b6ff44d6fc8bdfa0e17e9f5405d79a718ece4bcb338e61872000c21dae7dd64b7842b337ab5fdb14a002b30b5afecee94adbff1cc236840dabbc18fb1da1456b38bf7850284b6174e6a05cc2e4dde3eff7e2c75c453c11b8fece1b41bdb6090ea8627d576b1e832db828a07709d58e2bba23879bdcd7b8aa05d6bb20545ac87eb48ba5057e9a626e92dfc5a0e24436fade0021cb2fc0a7fc6c73d811361643604897451125b079dd138a897ea045f9c86ac0e893cde57833c6f5ae09553b28ca1afafca8ae2b3845bc25b34beca0985e4bc4b513176bf0f35a322ed93deefbcb1adb352ae41da0963e8283f26806a0150a60420b74add256c71f8ab0b317eab14da37ab2cc457edb91356cdcdf7aeea022d2d32fc7127330dc81871391b0604d4b0ff8d3ca1b4efe9dcb37481ecb6d6ca0e5869aaa00519d2afb3ad359fe6410edb0303bd6858d1b53da17a17d09ee96faa084e0fd6bad4e858e10da00073b38b731765445c75e553eb35221e8fd3e90dc2aa0c1f00d927970581cec0dd7e1552a07783ea4ee9dc0e393731cce6f9efc37abc7a0a241a2b6f90d1d7a6d4725bb2ce0e5e72f095747eff9c54dca78be4e85c252faa0985f79232dfcb1258237e26f2cff97a92edd90d772dcfe72fd3bf2101f86707f80f90211a04ad5cd0ae4d11d2f376a69e078eae424cfaccb95768aa8006ddc7fbf13ca4f03a086a86f7be7185cbece6733a640066459721e099c007f44d8f8bb596335926210a018e98a8487ce49b95e495de2e13d9e5b968c3cdcd8053bef4fadfd3087d61718a0b371218bdcdc42277010bd5bd13b69cdc55b6b72f66c0856dfcdc1b9c75944b0a0646bac97dd32742dc5f3e1d4bfafa0c371f5c8f4fb02f2d14adfb0093ce76ddaa01361d43d0cd74ab9f91b4404e2bb78320d2c256bff7d4578f5bbdf94e3108987a0419e3065d7c205531f349910f9b5e6028e77b731c5cab0d92d6ff3182cf3bdf2a0ee0d0537c2bd7d441ef92dbaec11c670dfa0a45f9aa8b10964fcd2bec9b980d1a059644ea6cc3b6d8b9f2e86ed0f85fe01480420396b68ab84f4f7ab35e835209fa026b4189f6b97801198e60a5504c9e72e45b858d46f54a42ab813477332242f00a0b5105f1c69c24daa343d154aa76dde988ed45264d29af893285ab2634cbff9d6a0be4607a85ed4d39a5e49d0e26a41497261e203d4037dfcec76345874b326b3eaa053e4d03ab09d7d9828458531ee50e283c2e6c6044f97627993fdda9d745f430ca0c688ce84423b6e624ccebc3a1a88ed175177cc47e8f36269e9621ece69fcaa5ba0caa77f081255a2b5623aad5e762a0654411841c4d957b69f24e73c8be08bbdb1a04ce24402babac9914ebe645ff0bc66d34d50dd161f04701e4b099ea934b7b21780f90211a0660423b2d895f2aba3813807e74edac3fb9538266bdb42babe1e5dd25c4fd161a04150b5a2aa96406d0177153c353d16867cbd34a08aae35de53107a0a0b25658fa073c31b0b234014004029140c8dd63f8f281fe5ecb996cc38444efaf9f58a6b97a0da59ee8a17b488874e1949304dd3fdac7cb82c69a2c97365f0d6197696e2d054a049ab40adfe47ee2651086f0b722eb6f9bae40357438352fb34d9e6973c058c86a0a9fd2355826bcb94e5060af6ee6a7af1c60a2fecbab3bb809bea3c9b60b2b16ba026f23be81e08afdcfe85483c7fe217a7a391380e6f1e60078fe1d978b3b9fab4a06d60fbb088071b0f783972eda652a900f52cc85a81fe5f85243f7ed94143ba43a0910d149ab3be02efd52b2f07582acf8e1f80dc8565f7a0a6c659446369f2f3a2a09d6abd23e6aa8665b109e26ae13ef2f07a74bfb7d88d2de4e8a5faf2a48cecfea01f2e48683177e9da2910e7b523222b3cf5dc793caaf5c7f606a5395a0cf4af5ea0fc7d5dcc4a69a762dbd014cf35704f079673eabfc15e33bcfe453e35261e4258a048893be539b2cd2832d2ee746c1dce63979f29c2c3661e68cdfe477919fd4fcda08134f7abcbd812300070e34101cb818cd6a929b92825794df7687c13793e1798a0c9c310d767aaeaef86f7001d8c603aca2f3a4fbdd9fc997b42021328d59a9200a006ea99e6b8ce70f2d160744de1dc3eef851ffb16c2e907669f9b20e692049c7780f901d1a0dc46d5c082d2f2c80e0b5182cc2329ceec32b68584efb95ae474ab6996b16405a0cb3b5857ff3e418aa100a37fd76ea07f11e9d20a8a25de15e7c5cf047f9bb1efa09539eb3d48355167d413df7084c6e4e2d16249fae03a426d58a23240c5eb6050a0b52f82379833886dcf5bc370050b201a6ca9ae6f8349377f37581b0fbd83ccbfa02ead36534a30cf5639013c89cbf5f287d126226d3215c293448f2dd1bc86efeea0477bdca5ac4012c525920e4c48a221d90bdd7e095839d8521a975d39575ede04a0f4c68a529743bb06e731591dc32d22fe6bfa147b7afaab71a7b60f4dc122537ea01ae2e537cff6e6e3ae2489049e230cc5e3de39a0a6fd1e5ccf5d6363284b31ada056cbeef705e4a661cb1e829854e8f7c695dfa7522137924b65a582e6f30df837a0889deb18807278808e153de8ef29a518bb3352f91c6debd63d0126309bbe7e5c80a09c2c9d8df97055c3594088cdaa0d105ef463073b68c5f9ed317f280d00276545a0c91b1d73b891626ea90d6301139f21f8270555ad92bf6614d8eec619c51623c480a0bcb691927c8fe0073e0dde266e63976dfd449de4a827d29937f7f2d28b9798b4a0ca3a8558ef41a0ed62d11d38c907e439aa75f94ee490f98d135e0a5bbfc1e58f80f8718080a023b74a8c299a6e63cbd07b7b96f314cb3eb8b881efd645478cd1fb4a8ce6effca08f7176c73f5dfb1f19eab4fb00e33ed9541e40aee865cad1c7a291bdcf0600fb80808080808080a0915964c5f883d8ba02b81498e8ad3876f750fd3a19efb52f5553409a90f400fc8080808080f85180808080a0152357eb75eaa46b66aa3d777243bdee179a4c62ed78ecebe95e52611551d0ca8080a0851ce61f6802498c2096b2151bf87a67bdc89a105f75a4b2e7df77213e1f1e42808080808080808080f8669d2071b037cfc7f1b352780f45be6b97b02cca1ea9adf861c3a66e3f6953b846f8440180a042af08184d99bd2aa1b39b35e2764bda2d3a8690e7a8a15203db1c30f51fa350a04ab3ab54c1f8633aa6651140bc32f687c11f416b07ab8cedac30b8a9a01f7b11","blockHash":"0xa62c59f7a251084cdc91ddea474cbd004bd7313b8bef9bd9238420115b4c3a0c","blockHeaderRLP":"0xf9025ca05a1865fd898fdd7ba4652f12e1bc71bb3650badec9ebcbcc345f527897353803a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794670b24610df99b1685aeac0dfd5307b92e0cf4d7a027530029980a77dd08dcc982fe062d7c7c1479408e79ff58340be45806909f4ca02d74de20e58ff7fa9e7009f65f1091a54539b666041c8a62241ba47d9e935b80a07ca2ce0da426d57e7efc9686a5eb2b2831e8c04b1e08ee367616d7185600bab3b901000924129ccd48f0200411485287202a203048e5605363c0506008a9104488404241889004020424150082040b3234018844104510030264250022124e24248000502f410b1c46000a5408011f8030d801440089068104104c841018a6903012070a2440c70a01a81322222c0a5185092c800c00c90041080042201050118803050b6214000b842d216d006020020a00f2983044d1f22016040085010505485001228ca003340060560a40aa45000004a9094942b9c686010b08e0220222ca718581101a464001110238870201dcaa02194044000081018a8211775a22070865b12190a208458ee022094230402892dc0a808a99b2481022d004080d080021404580836a3b718401c9c38083a97fc184671f52f0914e65746865726d696e642d312e32392e31a013fd858a6063ad8bfe7125dcb9bca7b460cfba667716fcbdf84453415c3918fe88000000000000000085014a912a02a0e0ae2f315d9dfed0cd1b60580c6c7115721eef628f2b84b69df66f775ad34abf830c000083020000a0897a3d563c5a17bb4988089facb2dfb5eef7d385db64def7db91dfba1ee126c8","blockNumber":6962033,"checkpoint":{"fromBlockNumber":"6962032","votes":"100000000000000000"},"checkpointsSlot":"0x0000000000000000000000000000000000000000000000000000000000000011","checkpointsSlotHash":"0x7a18e34a98abd3f75f7fae004fd3e105ecbbe8069d15fd681ac333c6a9361dc2","numCheckpoints":1,"numCheckpointsSlot":"0x0000000000000000000000000000000000000000000000000000000000000010","numCheckpointsSlotHash":"0x3dbec2fe4782522edad30a15deeb9d7945f002ab48536039e7c5159f681d0130","xvsVaultAddress":"0x1129f882eAa912aE6D4f6D445b2E2b1eCbA99fd5","xvsVaultCheckpointsStorageProofRlp":"0xf90244f90211a06b13e146c561442f5920b14e0c951980e1c49792134a2f821cc66ef3ecf073e6a0ceb2d033e6f06dd212af278d3a1c262e16ebb70ef71cfa2601ba60a425b5ecf3a036e1c719852d320874025f801ce37c93acc8778f7239675b1c72459d7b930e67a068d03bce23cfdda3592d5b53c76a17b6f9c4c2a5416d20b05c6a4885773c5f2ba0cfe85b098ae712457e24637cf7ebdbbdbba54f20cbdaae7a66937dcfa5d1ffd3a0dce6d96764249dcde6972317b88f2030d5fb0ea6ded0c19eb7b3285c5731c4faa018291384f807f66b96a2865fb9575241f6e0dbcae05c2434919275a2f1016e10a0f87cf04cbe6a230538306e2df8fd748807b6a7133ed2927d9a017b1d54a46082a076fe24e853626849b26cdd63176eaf83ca0a8998426a4a4bb8b943d10bd48b38a0de9681719c686751a4700c73b75b9355405547b60396d82d0b384c8c9be0cacca044c58811a4c259cabeb868913e5d4ae85a02b22424fa6af60d6994c1ce259485a054eedfa0796a2f85b4b853146c92187494d9569bfc8a20ee0e0af5d6872bea82a033930ec3992aafbbcab7d6d4672efb9c10cca49c0dd3f104f4708efebe6fbaf1a0bb74af010cde0a9568239e7053b011d132d700b47cf07948f2de9b6a23a4c0c0a08e4256e246c746a690dae3dcd5befb78fa7972f5caae08089f937f000960cf12a0254817906244bcdac3379f661298ed4a7b44b53fd5ad836c37d30a712471c3b580efa03ca5c5f1f9d0578d08b165798fb3a2a1059bd2fcc284d792d71e57a8957197b78d8c016345785d8a0000006a3b70","xvsVaultNumCheckpointsStorageProofRlp":"0xf9033cf90211a06b13e146c561442f5920b14e0c951980e1c49792134a2f821cc66ef3ecf073e6a0ceb2d033e6f06dd212af278d3a1c262e16ebb70ef71cfa2601ba60a425b5ecf3a036e1c719852d320874025f801ce37c93acc8778f7239675b1c72459d7b930e67a068d03bce23cfdda3592d5b53c76a17b6f9c4c2a5416d20b05c6a4885773c5f2ba0cfe85b098ae712457e24637cf7ebdbbdbba54f20cbdaae7a66937dcfa5d1ffd3a0dce6d96764249dcde6972317b88f2030d5fb0ea6ded0c19eb7b3285c5731c4faa018291384f807f66b96a2865fb9575241f6e0dbcae05c2434919275a2f1016e10a0f87cf04cbe6a230538306e2df8fd748807b6a7133ed2927d9a017b1d54a46082a076fe24e853626849b26cdd63176eaf83ca0a8998426a4a4bb8b943d10bd48b38a0de9681719c686751a4700c73b75b9355405547b60396d82d0b384c8c9be0cacca044c58811a4c259cabeb868913e5d4ae85a02b22424fa6af60d6994c1ce259485a054eedfa0796a2f85b4b853146c92187494d9569bfc8a20ee0e0af5d6872bea82a033930ec3992aafbbcab7d6d4672efb9c10cca49c0dd3f104f4708efebe6fbaf1a0bb74af010cde0a9568239e7053b011d132d700b47cf07948f2de9b6a23a4c0c0a08e4256e246c746a690dae3dcd5befb78fa7972f5caae08089f937f000960cf12a0254817906244bcdac3379f661298ed4a7b44b53fd5ad836c37d30a712471c3b580f891a0c85136f04b3eacd0306912504cdf10ff91fc78ca6c1a2175f67cbae67c363e13a08207b298cd904700083965f169a6588c9eae2c35772d2074610b2a5e71d54f8e808080808080808080a070be13b403c36b215538a036d87ec87d8ea4f553b8f7ecb6a4355202b4e68bb2a02317eb09881e705352a221f27a0da7e922563414a8e88d8b88cfbaea1dee315380808080f87180808080a0bf9e3745641ec8321cab5c304d342a00cee6e036ef6f9f57c31e19d6379e1b8880808080808080a024d549fe7f4b14475328474853c3046bb5faaa1b4b180c2cf295241266e16c08a054739297fafd81d064ea90688cb00a1b92f83bb1b9430f53efccab07f51bf682808080e19f3230382301bc735e3d2fadbef69d56b6ebf99d47ba075f53929dadb7f7324001"} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 3d286289..1b66dda6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3178,6 +3178,13 @@ __metadata: languageName: node linkType: hard +"@types/json-stable-stringify@npm:^1.0.36": + version: 1.0.36 + resolution: "@types/json-stable-stringify@npm:1.0.36" + checksum: 765b07589e11a3896c3d06bb9e3a9be681e7edd95adf27370df0647a91bd2bfcfaf0e091fd4a13729343b388973f73f7e789d6cc62ab988240518a2d27c4a4e2 + languageName: node + linkType: hard + "@types/lru-cache@npm:^5.1.0": version: 5.1.1 resolution: "@types/lru-cache@npm:5.1.1" @@ -3450,29 +3457,7 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/governance-contracts@npm:^1.4.0": - version: 1.4.0 - resolution: "@venusprotocol/governance-contracts@npm:1.4.0" - dependencies: - "@venusprotocol/solidity-utilities": ^1.1.0 - hardhat-deploy-ethers: ^0.3.0-beta.13 - module-alias: ^2.2.2 - checksum: 85c6b6a815edb0befa4c38e3652a58464827d390620210b99575c16960ee6505e95e7c2192ebc972da7ed758d3c62e150d32fbdd1f01acab1731f29b11d1884e - languageName: node - linkType: hard - -"@venusprotocol/governance-contracts@npm:^2.0.0": - version: 2.3.0 - resolution: "@venusprotocol/governance-contracts@npm:2.3.0" - dependencies: - "@venusprotocol/solidity-utilities": 2.0.0 - hardhat-deploy-ethers: ^0.3.0-beta.13 - module-alias: ^2.2.2 - checksum: b7c6054d36f435e6360acbe5ef31816901377bffb119147a519c7aa93f8ad4205dfbb85deb706a5fbc37ab144dfdb42284f18c8e95bc729a780303c828221891 - languageName: node - linkType: hard - -"@venusprotocol/governance-contracts@workspace:.": +"@venusprotocol/governance-contracts@^2.0.0, @venusprotocol/governance-contracts@workspace:.": version: 0.0.0-use.local resolution: "@venusprotocol/governance-contracts@workspace:." dependencies: @@ -3493,7 +3478,7 @@ __metadata: "@nomicfoundation/hardhat-network-helpers": ^1.0.6 "@nomicfoundation/hardhat-toolbox": ^2.0.0 "@nomicfoundation/hardhat-verify": ^2.0.8 - "@nomiclabs/hardhat-ethers": ^2.2.1 + "@nomiclabs/hardhat-ethers": ^2.2.3 "@nomiclabs/hardhat-etherscan": ^3.1.2 "@openzeppelin/contracts": ^4.8.2 "@openzeppelin/contracts-upgradeable": ^4.8.2 @@ -3506,6 +3491,7 @@ __metadata: "@types/chai": ^4.3.4 "@types/debug": ^4.1.12 "@types/fs-extra": ^9.0.13 + "@types/json-stable-stringify": ^1.0.36 "@types/mocha": ^10.0.0 "@types/node": ^18.16.3 "@typescript-eslint/eslint-plugin": ^5.44.0 @@ -3529,6 +3515,7 @@ __metadata: hardhat-docgen: ^1.3.0 hardhat-gas-reporter: ^1.0.9 husky: ^8.0.3 + json-stable-stringify: ^1.1.1 lint-staged: ^13.0.4 lodash: ^4.17.21 mocha: ^10.1.0 @@ -3551,6 +3538,17 @@ __metadata: languageName: unknown linkType: soft +"@venusprotocol/governance-contracts@npm:^1.4.0": + version: 1.4.0 + resolution: "@venusprotocol/governance-contracts@npm:1.4.0" + dependencies: + "@venusprotocol/solidity-utilities": ^1.1.0 + hardhat-deploy-ethers: ^0.3.0-beta.13 + module-alias: ^2.2.2 + checksum: 85c6b6a815edb0befa4c38e3652a58464827d390620210b99575c16960ee6505e95e7c2192ebc972da7ed758d3c62e150d32fbdd1f01acab1731f29b11d1884e + languageName: node + linkType: hard + "@venusprotocol/protocol-reserve@npm:^1.4.0": version: 1.5.0 resolution: "@venusprotocol/protocol-reserve@npm:1.5.0" @@ -9862,6 +9860,18 @@ __metadata: languageName: node linkType: hard +"json-stable-stringify@npm:^1.1.1": + version: 1.1.1 + resolution: "json-stable-stringify@npm:1.1.1" + dependencies: + call-bind: ^1.0.5 + isarray: ^2.0.5 + jsonify: ^0.0.1 + object-keys: ^1.1.1 + checksum: e1ba06600fd278767eeff53f28e408e29c867e79abf564e7aadc3ce8f31f667258f8db278ef28831e45884dd687388fa1910f46e599fc19fb94c9afbbe3a4de8 + languageName: node + linkType: hard + "json-stringify-nice@npm:^1.1.4": version: 1.1.4 resolution: "json-stringify-nice@npm:1.1.4" @@ -9933,6 +9943,13 @@ __metadata: languageName: node linkType: hard +"jsonify@npm:^0.0.1": + version: 0.0.1 + resolution: "jsonify@npm:0.0.1" + checksum: 027287e1c0294fce15f18c0ff990cfc2318e7f01fb76515f784d5cd0784abfec6fc5c2355c3a2f2cb0ad7f4aa2f5b74ebbfe4e80476c35b2d13cabdb572e1134 + languageName: node + linkType: hard + "jsonparse@npm:^1.2.0, jsonparse@npm:^1.3.1": version: 1.3.1 resolution: "jsonparse@npm:1.3.1"