diff --git a/contracts/identitytreestore/IdentityTreeStore.sol b/contracts/identitytreestore/IdentityTreeStore.sol index a2a4eaefe..a4034889f 100644 --- a/contracts/identitytreestore/IdentityTreeStore.sol +++ b/contracts/identitytreestore/IdentityTreeStore.sol @@ -7,6 +7,7 @@ import {IState} from "../interfaces/IState.sol"; import {IOnchainCredentialStatusResolver} from "../interfaces/IOnchainCredentialStatusResolver.sol"; import {IRHSStorage} from "../interfaces/IRHSStorage.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; error NodeNotFound(); error InvalidStateNode(); @@ -32,7 +33,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I /** * @dev Version of contract */ - string public constant VERSION = "1.1.0"; + string public constant VERSION = "2.0.0"; /** * @dev Max SMT depth for the CredentialStatus proof @@ -59,6 +60,7 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I /// @custom:storage-location erc7201:iden3.storage.IdentityTreeStore.Main struct IdentityTreeStoreMainStorage { IState _state; + IHasher _hasher; } // keccak256(abi.encode(uint256(keccak256("iden3.storage.IdentityTreeStore.Main")) - 1)) & ~bytes32(uint256(0xff)); @@ -81,13 +83,22 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I /** * @dev Function to call first time for initialization of the proxy. * @param state The state contract address to be used to check state of the identities + * @param hasher The hasher to use in hashFunction **/ - function initialize(address state) public initializer { - IdentityTreeStoreMainStorage storage $its = _getIdentityTreeStoreMainStorage(); - ReverseHashLib.Data storage $rhl = _getReverseHashLibDataStorage(); + function initialize(address state, IHasher hasher) public initializer { + _getIdentityTreeStoreMainStorage()._state = IState(state); + _initializeHasher(hasher); + } - $its._state = IState(state); - $rhl.hashFunction = _hashFunc; + /** + * @dev Initialize needed data + * @param hasher Hasher for SmtLib + */ + function initializeHasher(IHasher hasher) external reinitializer(2) { + // Initialize in case the hasher has not been set yet + if (address(_getIdentityTreeStoreMainStorage()._hasher) == address(0)) { + _initializeHasher(hasher); + } } /** @@ -98,6 +109,10 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I return _getReverseHashLibDataStorage().savePreimages(nodes); } + function getStateAddress() external view returns (IState) { + return _getIdentityTreeStoreMainStorage()._state; + } + /** * @dev Returns a node by its key. Note that a node contains an array. * @param key The key of the node @@ -241,13 +256,19 @@ contract IdentityTreeStore is Initializable, IOnchainCredentialStatusResolver, I return NodeType.Unknown; } - function _hashFunc(uint256[] memory preimage) internal pure returns (uint256) { + function _hashFunc(uint256[] memory preimage) internal view returns (uint256) { + IdentityTreeStoreMainStorage storage $its = _getIdentityTreeStoreMainStorage(); if (preimage.length == 2) { - return PoseidonUnit2L.poseidon([preimage[0], preimage[1]]); + return $its._hasher.hash2([preimage[0], preimage[1]]); } if (preimage.length == 3) { - return PoseidonUnit3L.poseidon([preimage[0], preimage[1], preimage[2]]); + return $its._hasher.hash3([preimage[0], preimage[1], preimage[2]]); } revert UnsupportedLength(); } + + function _initializeHasher(IHasher hasher) internal { + _getIdentityTreeStoreMainStorage()._hasher = hasher; + _getReverseHashLibDataStorage().hashFunction = _hashFunc; + } } diff --git a/contracts/interfaces/IHasher.sol b/contracts/interfaces/IHasher.sol new file mode 100644 index 000000000..d7b3d8a38 --- /dev/null +++ b/contracts/interfaces/IHasher.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.27; + +/** + * @dev IHasher. Interface for generating hashes. Specifically used for Merkle Tree hashing. + */ +interface IHasher { + /** + * @dev hash1. hashes one uint256 parameter and returns the resulting hash as uint256. + * @param params The parameters array of size 1 to be hashed. + * @return The resulting hash as uint256. + */ + function hash1(uint256[1] memory params) external pure returns (uint256); + + /** + * @dev hash2. hashes two uint256 parameters and returns the resulting hash as uint256. + * @param params The parameters array of size 2 to be hashed. + * @return The resulting hash as uint256. + */ + function hash2(uint256[2] memory params) external pure returns (uint256); + + /** + * @dev hash3. hashes three uint256 parameters and returns the resulting hash as uint256. + * @param params The parameters array of size 3 to be hashed. + * @return The resulting hash as uint256. + */ + function hash3(uint256[3] memory params) external pure returns (uint256); +} diff --git a/contracts/lib/IdentityBase.sol b/contracts/lib/IdentityBase.sol index 3c5c88879..242705f74 100644 --- a/contracts/lib/IdentityBase.sol +++ b/contracts/lib/IdentityBase.sol @@ -6,6 +6,7 @@ import {IOnchainCredentialStatusResolver} from "../interfaces/IOnchainCredential import {IdentityLib} from "../lib/IdentityLib.sol"; import {SmtLib} from "../lib/SmtLib.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; error IdentityIdMismatch(); @@ -46,12 +47,13 @@ abstract contract IdentityBase is IIdentifiable, IOnchainCredentialStatusResolve * @dev Initialization of IdentityLib library * @param _stateContractAddr - address of the State contract */ - function initialize(address _stateContractAddr, bytes2 idType) public virtual { + function initialize(address _stateContractAddr, bytes2 idType, IHasher hasher) public virtual { _getIdentityBaseStorage().identity.initialize( _stateContractAddr, address(this), getSmtDepth(), - idType + idType, + hasher ); } diff --git a/contracts/lib/IdentityLib.sol b/contracts/lib/IdentityLib.sol index 330fb63c2..bc0253318 100644 --- a/contracts/lib/IdentityLib.sol +++ b/contracts/lib/IdentityLib.sol @@ -5,6 +5,7 @@ import {IState} from "../interfaces/IState.sol"; import {SmtLib} from "../lib/SmtLib.sol"; import {PoseidonUnit3L, PoseidonUnit4L} from "../lib/Poseidon.sol"; import {GenesisUtils} from "../lib/GenesisUtils.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; error SMTDepthIsGreaterThanMaxAllowed(); error IdTypeNotSupported(); @@ -86,7 +87,8 @@ library IdentityLib { address _stateContractAddr, address _identityAddr, uint256 depth, - bytes2 idType + bytes2 idType, + IHasher hasher ) external { if (depth > IDENTITY_MAX_SMT_DEPTH) { revert SMTDepthIsGreaterThanMaxAllowed(); @@ -96,9 +98,9 @@ library IdentityLib { revert IdTypeNotSupported(); } self.isOldStateGenesis = true; - self.trees.claimsTree.initialize(depth); - self.trees.revocationsTree.initialize(depth); - self.trees.rootsTree.initialize(depth); + self.trees.claimsTree.initialize(depth, hasher); + self.trees.revocationsTree.initialize(depth, hasher); + self.trees.rootsTree.initialize(depth, hasher); self.id = GenesisUtils.calcIdFromEthAddress(idType, _identityAddr); } diff --git a/contracts/lib/ReverseHashLib.sol b/contracts/lib/ReverseHashLib.sol index d942ec34d..071429615 100644 --- a/contracts/lib/ReverseHashLib.sol +++ b/contracts/lib/ReverseHashLib.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.27; library ReverseHashLib { struct Data { mapping(uint256 => uint256[]) hashesToPreimages; - function(uint256[] memory) pure returns (uint256) hashFunction; + function(uint256[] memory) view returns (uint256) hashFunction; } /** diff --git a/contracts/lib/SmtLib.sol b/contracts/lib/SmtLib.sol index 809fb86c0..fabb8fff1 100644 --- a/contracts/lib/SmtLib.sol +++ b/contracts/lib/SmtLib.sol @@ -1,16 +1,31 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.27; -import {PoseidonUnit2L, PoseidonUnit3L} from "./Poseidon.sol"; import {ArrayUtils} from "./ArrayUtils.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; /// @title A sparse merkle tree implementation, which keeps tree history. // Note that this SMT implementation can manage duplicated roots in the history, // which may happen when some leaf change its value and then changes it back to the original value. -// Leaves deletion is not supported, although it should be possible to implement it in the future -// versions of this library, without changing the existing state variables -// In this way all the SMT data may be preserved for the contracts already in production. +// Leaves deletion is supported via removeLeaf, which preserves all existing state variables +// and the SMT root history. All previously recorded roots remain accessible. library SmtLib { + error NodeHashConflict( + uint256 nodeHash, + uint8 existingNodeType, + uint8 newNodeType, + uint256 existingChildLeft, + uint256 newChildLeft, + uint256 existingChildRight, + uint256 newChildRight, + uint256 existingIndex, + uint256 newIndex, + uint256 existingValue, + uint256 newValue + ); + + error HasherHasNotBeenSet(); + /** * @dev Max return array length for SMT root history requests */ @@ -49,11 +64,17 @@ library SmtLib { mapping(uint256 => uint256[]) rootIndexes; // root => rootEntryIndex[] uint256 maxDepth; bool initialized; + // IHasher implementation to be used for hashing. + IHasher hasher; + // This is a workaround for the storage layout of the IHasher interface, + // which is an address (20 bytes) and a uint256 (32 bytes). + // We use a uint96 to fill the uint256 of uint256 gap used. + uint96 __gapHasher; // This empty reserved space is put in place to allow future versions // of the SMT library to add new Data struct fields without shifting down // storage of upgradable contracts that use this struct as a state variable // (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps) - uint256[45] __gap; + uint256[44] __gap; } /** @@ -136,6 +157,23 @@ library SmtLib { _; } + /** + * @dev Initialize custom hasher for the SMT. MUST be called before any other SMT operations. + * @param customHasher IHasher implementation to be used for hashing. + */ + function initializeHasher(Data storage self, IHasher customHasher) external { + require(address(customHasher) != address(0), "Invalid hasher"); + require(address(self.hasher) == address(0), "Hasher already set"); + self.hasher = customHasher; + } + + /** + * @dev Gets the custom hasher for the SMT. + */ + function getHasher(Data storage self) external view returns (IHasher) { + return self.hasher; + } + /** * @dev Add a leaf to the SMT * @param i Index of a leaf @@ -156,6 +194,37 @@ library SmtLib { _addEntry(self, newRoot, block.timestamp, block.number); } + /** + * @dev Update the value of an existing leaf in the SMT + * @param i Index of the leaf to update + * @param oldV Current value of the leaf (must match stored value) + * @param newV New value to set (must not be zero) + */ + function updateLeaf( + Data storage self, + uint256 i, + uint256 oldV, + uint256 newV + ) external onlyInitialized(self) { + require(newV != 0, "New leaf value should not be zero"); + + uint256 prevRoot = getRoot(self); + uint256 newRoot = _updateLeaf(self, i, oldV, newV, prevRoot, 0); + + _addEntry(self, newRoot, block.timestamp, block.number); + } + + /** + * @dev Remove a leaf from the SMT + * @param i Index of the leaf to remove + * @param oldV Current value of the leaf (must match stored value) + */ + function removeLeaf(Data storage self, uint256 i, uint256 oldV) external onlyInitialized(self) { + uint256 prevRoot = getRoot(self); + uint256 newRoot = _removeLeaf(self, i, oldV, prevRoot, 0); + _addEntry(self, newRoot, block.timestamp, block.number); + } + /** * @dev Get SMT root history length * @return SMT history length @@ -426,9 +495,11 @@ library SmtLib { * @dev Initialize SMT with max depth and root entry of an empty tree. * @param maxDepth Max depth of the SMT. */ - function initialize(Data storage self, uint256 maxDepth) external { + function initialize(Data storage self, uint256 maxDepth, IHasher hasher) external { require(!isInitialized(self), "Smt is already initialized"); + require(address(hasher) != address(0), "Invalid hasher"); setMaxDepth(self, maxDepth); + self.hasher = hasher; _addEntry(self, 0, 0, 0); self.initialized = true; } @@ -526,16 +597,16 @@ library SmtLib { if (newLeafBitAtDepth) { newNodeMiddle = Node({ nodeType: NodeType.MIDDLE, - childLeft: _getNodeHash(oldLeaf), - childRight: _getNodeHash(newLeaf), + childLeft: _getNodeHash(self, oldLeaf), + childRight: _getNodeHash(self, newLeaf), index: 0, value: 0 }); } else { newNodeMiddle = Node({ nodeType: NodeType.MIDDLE, - childLeft: _getNodeHash(newLeaf), - childRight: _getNodeHash(oldLeaf), + childLeft: _getNodeHash(self, newLeaf), + childRight: _getNodeHash(self, oldLeaf), index: 0, value: 0 }); @@ -546,16 +617,35 @@ library SmtLib { } function _addNode(Data storage self, Node memory node) internal returns (uint256) { - uint256 nodeHash = _getNodeHash(node); + uint256 nodeHash = _getNodeHash(self, node); // We don't have any guarantees if the hash function attached is good enough. // So, if the node hash already exists, we need to check // if the node in the tree exactly matches the one we are trying to add. if (self.nodes[nodeHash].nodeType != NodeType.EMPTY) { - assert(self.nodes[nodeHash].nodeType == node.nodeType); - assert(self.nodes[nodeHash].childLeft == node.childLeft); - assert(self.nodes[nodeHash].childRight == node.childRight); - assert(self.nodes[nodeHash].index == node.index); - assert(self.nodes[nodeHash].value == node.value); + Node memory existing = self.nodes[nodeHash]; + + if ( + existing.nodeType != node.nodeType || + existing.childLeft != node.childLeft || + existing.childRight != node.childRight || + existing.index != node.index || + existing.value != node.value + ) { + revert NodeHashConflict( + nodeHash, + uint8(existing.nodeType), + uint8(node.nodeType), + existing.childLeft, + node.childLeft, + existing.childRight, + node.childRight, + existing.index, + node.index, + existing.value, + node.value + ); + } + return nodeHash; } @@ -563,13 +653,18 @@ library SmtLib { return nodeHash; } - function _getNodeHash(Node memory node) internal pure returns (uint256) { + function _getNodeHash(Data storage self, Node memory node) internal view returns (uint256) { uint256 nodeHash = 0; + + if (address(self.hasher) == address(0)) { + revert HasherHasNotBeenSet(); + } + if (node.nodeType == NodeType.LEAF) { uint256[3] memory params = [node.index, node.value, uint256(1)]; - nodeHash = PoseidonUnit3L.poseidon(params); + nodeHash = self.hasher.hash3(params); } else if (node.nodeType == NodeType.MIDDLE) { - nodeHash = PoseidonUnit2L.poseidon([node.childLeft, node.childRight]); + nodeHash = self.hasher.hash2([node.childLeft, node.childRight]); } return nodeHash; // Note: expected to return 0 if NodeType.EMPTY, which is the only option left } @@ -619,6 +714,147 @@ library SmtLib { self.rootIndexes[root].push(self.rootEntries.length - 1); } + + function _updateLeaf( + Data storage self, + uint256 index, + uint256 oldValue, + uint256 newValue, + uint256 nodeHash, + uint256 depth + ) internal returns (uint256) { + if (depth > self.maxDepth) { + revert("Max depth reached"); + } + + Node memory node = self.nodes[nodeHash]; + + if (node.nodeType == NodeType.EMPTY) { + revert("Leaf does not exist"); + } + + if (node.nodeType == NodeType.LEAF) { + require(node.index == index, "Leaf index mismatch"); + require(node.value == oldValue, "Old value mismatch"); + + Node memory newLeaf = Node({ + nodeType: NodeType.LEAF, + childLeft: 0, + childRight: 0, + index: index, + value: newValue + }); + + return _addNode(self, newLeaf); + } + + Node memory newNode; + bool goRight = (index >> depth) & 1 == 1; + + if (goRight) { + uint256 updatedRight = _updateLeaf( + self, + index, + oldValue, + newValue, + node.childRight, + depth + 1 + ); + + newNode = Node({ + nodeType: NodeType.MIDDLE, + childLeft: node.childLeft, + childRight: updatedRight, + index: 0, + value: 0 + }); + } else { + uint256 updatedLeft = _updateLeaf( + self, + index, + oldValue, + newValue, + node.childLeft, + depth + 1 + ); + + newNode = Node({ + nodeType: NodeType.MIDDLE, + childLeft: updatedLeft, + childRight: node.childRight, + index: 0, + value: 0 + }); + } + + return _addNode(self, newNode); + } + + function _removeLeaf( + Data storage self, + uint256 index, + uint256 oldValue, + uint256 nodeHash, + uint256 depth + ) internal returns (uint256) { + if (depth > self.maxDepth) { + revert("Max depth reached"); + } + + Node memory node = self.nodes[nodeHash]; + + if (node.nodeType == NodeType.EMPTY) { + revert("Leaf does not exist"); + } + + if (node.nodeType == NodeType.LEAF) { + require(node.index == index, "Leaf index mismatch"); + require(node.value == oldValue, "Old value mismatch"); + return 0; + } + + bool goRight = (index >> depth) & 1 == 1; + uint256 newChildHash; + uint256 siblingHash; + + if (goRight) { + newChildHash = _removeLeaf(self, index, oldValue, node.childRight, depth + 1); + siblingHash = node.childLeft; + } else { + newChildHash = _removeLeaf(self, index, oldValue, node.childLeft, depth + 1); + siblingHash = node.childRight; + } + + return _applyPathCompression(self, goRight, newChildHash, siblingHash); + } + + function _applyPathCompression( + Data storage self, + bool goRight, + uint256 newChildHash, + uint256 siblingHash + ) internal returns (uint256) { + // If the removed side is now empty, try to lift the sibling + if (newChildHash == 0) { + if (siblingHash == 0) { + return 0; + } + if (self.nodes[siblingHash].nodeType == NodeType.LEAF) { + return siblingHash; + } + } + + // If the sibling was already empty and the surviving child is a lifted + // leaf from a deeper compression, propagate the lift upward + if (siblingHash == 0 && self.nodes[newChildHash].nodeType == NodeType.LEAF) { + return newChildHash; + } + + if (goRight) { + return _addNode(self, Node(NodeType.MIDDLE, siblingHash, newChildHash, 0, 0)); + } + return _addNode(self, Node(NodeType.MIDDLE, newChildHash, siblingHash, 0, 0)); + } } /// @title A binary search for the sparse merkle tree root history diff --git a/contracts/lib/hash/KeccakHasher.sol b/contracts/lib/hash/KeccakHasher.sol new file mode 100644 index 000000000..d3b38e579 --- /dev/null +++ b/contracts/lib/hash/KeccakHasher.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.27; + +import {IHasher} from "../../interfaces/IHasher.sol"; + +/// @title A IHasher implementation using Keccak256. +contract Keccak256Hasher is IHasher { + function hash1(uint256[1] memory params) external pure override returns (uint256) { + bytes memory encoded = abi.encode(params); + return uint256(keccak256(encoded)); + } + + function hash2(uint256[2] memory params) external pure override returns (uint256) { + bytes memory encoded = abi.encode(params); + return uint256(keccak256(encoded)); + } + + function hash3(uint256[3] memory params) external pure override returns (uint256) { + bytes memory encoded = abi.encode(params); + return uint256(keccak256(encoded)); + } +} diff --git a/contracts/lib/hash/PoseidonHasher.sol b/contracts/lib/hash/PoseidonHasher.sol new file mode 100644 index 000000000..34ac80dfe --- /dev/null +++ b/contracts/lib/hash/PoseidonHasher.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.27; + +import {IHasher} from "../../interfaces/IHasher.sol"; +import {PoseidonUnit1L, PoseidonUnit2L, PoseidonUnit3L} from "../Poseidon.sol"; + +/// @title A IHasher implementation using Poseidon. +contract PoseidonHasher is IHasher { + function hash1(uint256[1] memory params) external pure override returns (uint256) { + return PoseidonUnit1L.poseidon(params); + } + + function hash2(uint256[2] memory params) external pure override returns (uint256) { + return PoseidonUnit2L.poseidon(params); + } + + function hash3(uint256[3] memory params) external pure override returns (uint256) { + return PoseidonUnit3L.poseidon(params); + } +} diff --git a/contracts/package-lock.json b/contracts/package-lock.json index c7a8c9f55..666f3e141 100644 --- a/contracts/package-lock.json +++ b/contracts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@iden3/contracts", - "version": "3.5.0", + "version": "3.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@iden3/contracts", - "version": "3.5.0", + "version": "3.5.1", "license": "GPL-3.0", "dependencies": { "@openzeppelin/contracts": "5.4.0", diff --git a/contracts/package.json b/contracts/package.json index c10116dea..8bf497694 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@iden3/contracts", "description": "Smart Contract library for Solidity", - "version": "3.5.0", + "version": "3.5.1", "files": [ "**/*.sol", "/build/contracts/*.json", diff --git a/contracts/state/State.sol b/contracts/state/State.sol index ed6f5b425..ce72c5a4d 100644 --- a/contracts/state/State.sol +++ b/contracts/state/State.sol @@ -5,17 +5,17 @@ import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/acces import {IState, MAX_SMT_DEPTH} from "../interfaces/IState.sol"; import {IStateTransitionVerifier} from "../interfaces/IStateTransitionVerifier.sol"; import {SmtLib} from "../lib/SmtLib.sol"; -import {PoseidonUnit1L} from "../lib/Poseidon.sol"; import {StateLib} from "../lib/StateLib.sol"; import {GenesisUtils} from "../lib/GenesisUtils.sol"; import {ICrossChainProofValidator} from "../interfaces/ICrossChainProofValidator.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; /// @title Set and get states for each identity contract State is Ownable2StepUpgradeable, IState { /** * @dev Version of contract */ - string public constant VERSION = "2.6.3"; + string public constant VERSION = "3.0.0"; /** * @dev Global state proof type */ @@ -25,6 +25,11 @@ contract State is Ownable2StepUpgradeable, IState { */ bytes32 private constant STATE_PROOF_TYPE = keccak256(bytes("stateProof")); + /** + * @dev Hasher for SmtLib + */ + IHasher internal _hasher; + // This empty reserved space is put in place to allow future versions // of the State contract to inherit from other contracts without a risk of // breaking the storage layout. This is necessary because the parent contracts in the @@ -33,7 +38,7 @@ contract State is Ownable2StepUpgradeable, IState { // (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps) // slither-disable-next-line shadowing-state // slither-disable-next-line unused-state - uint256[651] private __gap; + uint256[650] private __gap; /** * @dev Verifier address @@ -94,15 +99,17 @@ contract State is Ownable2StepUpgradeable, IState { * @param defaultIdType default id type for Ethereum-based IDs calculation * @param owner Owner of the contract with administrative functions * @param validator Cross chain proof validator contract address + * @param hasher Hasher for SmtLib */ function initialize( IStateTransitionVerifier verifierContractAddr, bytes2 defaultIdType, address owner, - ICrossChainProofValidator validator + ICrossChainProofValidator validator, + IHasher hasher ) public initializer { if (!_gistData.initialized) { - _gistData.initialize(MAX_SMT_DEPTH); + _gistData.initialize(MAX_SMT_DEPTH, hasher); } if (address(verifierContractAddr) == address(0)) { @@ -114,6 +121,19 @@ contract State is Ownable2StepUpgradeable, IState { __Ownable_init(owner); StateCrossChainStorage storage $ = _getStateCrossChainStorage(); $._crossChainProofValidator = validator; + _hasher = hasher; + } + + /** + * @dev Initialize hasher for State and SmtLib + * @param hasher Hasher for State and SmtLib + */ + function initializeHasher(IHasher hasher) external reinitializer(2) { + // Initialize in case the hasher has not been set yet + if (address(_hasher) == address(0)) { + _hasher = hasher; + _gistData.initializeHasher(hasher); + } } /** @@ -332,7 +352,7 @@ contract State is Ownable2StepUpgradeable, IState { * @return The GIST inclusion or non-inclusion proof for the identity */ function getGISTProof(uint256 id) external view returns (IState.GistProof memory) { - return _smtProofAdapter(_gistData.getProof(PoseidonUnit1L.poseidon([id]))); + return _smtProofAdapter(_gistData.getProof(_hasher.hash1([id]))); } /** @@ -346,7 +366,7 @@ contract State is Ownable2StepUpgradeable, IState { uint256 id, uint256 root ) external view returns (IState.GistProof memory) { - return _smtProofAdapter(_gistData.getProofByRoot(PoseidonUnit1L.poseidon([id]), root)); + return _smtProofAdapter(_gistData.getProofByRoot(_hasher.hash1([id]), root)); } /** @@ -360,8 +380,7 @@ contract State is Ownable2StepUpgradeable, IState { uint256 id, uint256 blockNumber ) external view returns (IState.GistProof memory) { - return - _smtProofAdapter(_gistData.getProofByBlock(PoseidonUnit1L.poseidon([id]), blockNumber)); + return _smtProofAdapter(_gistData.getProofByBlock(_hasher.hash1([id]), blockNumber)); } /** @@ -375,7 +394,7 @@ contract State is Ownable2StepUpgradeable, IState { uint256 id, uint256 timestamp ) external view returns (IState.GistProof memory) { - return _smtProofAdapter(_gistData.getProofByTime(PoseidonUnit1L.poseidon([id]), timestamp)); + return _smtProofAdapter(_gistData.getProofByTime(_hasher.hash1([id]), timestamp)); } /** @@ -560,7 +579,7 @@ contract State is Ownable2StepUpgradeable, IState { // this checks that oldState != newState as well require(!stateExists(id, newState), "New state already exists"); _stateData.addState(id, newState); - _gistData.addLeaf(PoseidonUnit1L.poseidon([id]), newState); + _gistData.addLeaf(_hasher.hash1([id]), newState); } function _smtProofAdapter( diff --git a/contracts/test-helpers/BinarySearchTestWrapper.sol b/contracts/test-helpers/BinarySearchTestWrapper.sol index a7d7b6427..e2824c1d3 100644 --- a/contracts/test-helpers/BinarySearchTestWrapper.sol +++ b/contracts/test-helpers/BinarySearchTestWrapper.sol @@ -2,13 +2,14 @@ pragma solidity 0.8.27; import {SmtLib} from "../lib/SmtLib.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; contract BinarySearchTestWrapper { SmtLib.Data internal smtData; using SmtLib for SmtLib.Data; - constructor() { - smtData.initialize(64); + constructor(IHasher hasher) { + smtData.initialize(64, hasher); } function addRootEntry(uint256 root, uint256 createdAtTimestamp, uint256 createdAtBlock) public { diff --git a/contracts/test-helpers/IdentityExample.sol b/contracts/test-helpers/IdentityExample.sol index 1859a8a7e..2e3809664 100644 --- a/contracts/test-helpers/IdentityExample.sol +++ b/contracts/test-helpers/IdentityExample.sol @@ -5,6 +5,7 @@ import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/acces import {ClaimBuilder} from "../lib/ClaimBuilder.sol"; import {IdentityLib} from "../lib/IdentityLib.sol"; import {IdentityBase} from "../lib/IdentityBase.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; // /** // * @dev Contract managing onchain identity @@ -12,8 +13,12 @@ import {IdentityBase} from "../lib/IdentityBase.sol"; contract IdentityExample is IdentityBase, Ownable2StepUpgradeable { using IdentityLib for IdentityLib.Data; - function initialize(address _stateContractAddr, bytes2 _idType) public override initializer { - super.initialize(_stateContractAddr, _idType); + function initialize( + address _stateContractAddr, + bytes2 _idType, + IHasher hasher + ) public override initializer { + super.initialize(_stateContractAddr, _idType, hasher); __Ownable_init(_msgSender()); } diff --git a/contracts/test-helpers/SmtLibTestWrapper.sol b/contracts/test-helpers/SmtLibTestWrapper.sol index 5ca7d499b..b9647517c 100644 --- a/contracts/test-helpers/SmtLibTestWrapper.sol +++ b/contracts/test-helpers/SmtLibTestWrapper.sol @@ -2,20 +2,29 @@ pragma solidity 0.8.27; import {SmtLib} from "../lib/SmtLib.sol"; +import {IHasher} from "../interfaces/IHasher.sol"; contract SmtLibTestWrapper { using SmtLib for SmtLib.Data; SmtLib.Data internal smtData; - constructor(uint256 maxDepth) { - smtData.initialize(maxDepth); + constructor(uint256 maxDepth, IHasher hasher) { + smtData.initialize(maxDepth, hasher); } function add(uint256 i, uint256 v) public { smtData.addLeaf(i, v); } + function update(uint256 i, uint256 oldV, uint256 newV) public { + smtData.updateLeaf(i, oldV, newV); + } + + function remove(uint256 i, uint256 oldV) public { + smtData.removeLeaf(i, oldV); + } + function getProof(uint256 id) public view returns (SmtLib.Proof memory) { return smtData.getProof(id); } diff --git a/helpers/constants.ts b/helpers/constants.ts index 06079b940..08ef9a5a5 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -1,7 +1,7 @@ // HARDHAT network Oracle signing address -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); export const DEFAULT_MNEMONIC = "test test test test test test test test test test test junk"; @@ -186,7 +186,7 @@ export const contractsInfo = Object.freeze({ }, STATE: { name: "State", - version: "2.6.3", + version: "3.0.0", unifiedAddress: "0x3C9acB2205Aa72A05F6D77d708b5Cf85FCa3a896", create2Calldata: ethers.hexlify(ethers.toUtf8Bytes("iden3.create2.State")), verificationOpts: { @@ -374,7 +374,7 @@ export const contractsInfo = Object.freeze({ }, IDENTITY_TREE_STORE: { name: "IdentityTreeStore", - version: "1.1.0", + version: "2.0.0", unifiedAddress: "0x7dF78ED37d0B39Ffb6d4D527Bb1865Bf85B60f81", create2Calldata: ethers.hexlify(ethers.toUtf8Bytes("iden3.create2.IdentityTreeStore")), verificationOpts: { @@ -429,7 +429,7 @@ export const contractsInfo = Object.freeze({ }, SMT_LIB: { name: "SmtLib", - unifiedAddress: "0x682364078e26C1626abD2B95109D2019E241F0F6", + unifiedAddress: "0x9AB79dF17e50240e6090B3cccC98b0EB07170b3d", create2Calldata: "", verificationOpts: { constructorArgsImplementation: [], @@ -456,6 +456,11 @@ export const contractsInfo = Object.freeze({ unifiedAddress: "0x0695cF2c6dfc438a4E40508741888198A6ccacC2", create2Calldata: "", }, + POSEIDON_HASHER: { + name: "PoseidonHasher", + unifiedAddress: "0xc5Ce2d152DDf9e99250e8385DFFbF960bfA580e1", + create2Calldata: "", + }, GROTH16_VERIFIER_STATE_TRANSITION: { name: "Groth16VerifierStateTransition", unifiedAddress: "", diff --git a/helpers/helperUtils.ts b/helpers/helperUtils.ts index 699583ba3..9621887d6 100644 --- a/helpers/helperUtils.ts +++ b/helpers/helperUtils.ts @@ -9,12 +9,12 @@ import { } from "./constants"; import { poseidonContract } from "circomlibjs"; import path from "path"; -import hre, { network } from "hardhat"; +import hre from "hardhat"; import { verifyContract as hardhatVerifyContract } from "@nomicfoundation/hardhat-verify/verify"; const __dirname = path.resolve(); -const { ethers, provider, networkName } = await network.connect(); +const { ethers, provider, networkName } = await hre.network.create(); export function getConfig() { return { diff --git a/ignition/modules/contractsAt.ts b/ignition/modules/contractsAt.ts index cabc315cc..6e6ecba8f 100644 --- a/ignition/modules/contractsAt.ts +++ b/ignition/modules/contractsAt.ts @@ -32,6 +32,12 @@ export const Poseidon4AtModule = buildModule("Poseidon4AtModule", (m) => { return { contract }; }); +export const PoseidonHasherAtModule = buildModule("PoseidonHasherAtModule", (m) => { + const contractAddress = m.getParameter("contractAddress"); + const contract = m.contractAt(contractsInfo.POSEIDON_HASHER.name, contractAddress); + return { contract }; +}); + export const SmtLibAtModule = buildModule("SmtLibAtModule", (m) => { const contractAddress = m.getParameter("contractAddress"); const contract = m.contractAt(contractsInfo.SMT_LIB.name, contractAddress); diff --git a/ignition/modules/deployEverythingBasicStrategy/deployEverythingBasicStrategy.ts b/ignition/modules/deployEverythingBasicStrategy/deployEverythingBasicStrategy.ts index cace76bdb..55c6c6936 100644 --- a/ignition/modules/deployEverythingBasicStrategy/deployEverythingBasicStrategy.ts +++ b/ignition/modules/deployEverythingBasicStrategy/deployEverythingBasicStrategy.ts @@ -9,15 +9,14 @@ import AuthV2ValidatorModule from "./authV2Validator"; import IdentityTreeStoreModule from "./identityTreeStore"; import MCPaymentModule from "./mcPayment"; import VCPaymentModule from "./vcPayment"; -import UniversalVerifier_ManyResponsesPerUserAndRequestModule from "./universalVerifier_ManyResponsesPerUserAndRequest"; -import { network } from "hardhat"; +import hre from "hardhat"; import AuthV3ValidatorModule from "./authV3Validator"; import AuthV3_8_32ValidatorModule from "./authV3_8_32Validator"; import CredentialAtomicQueryV3StableValidatorModule from "./credentialAtomicQueryV3StableValidator"; import LinkedMultiQueryStableValidatorModule from "./linkedMultiQueryStableValidator"; import { contractsInfo } from "../../../helpers/constants"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const DeployEverythingBasicStrategy = buildModule("DeployEverythingBasicStrategy", (m) => { const { @@ -29,6 +28,7 @@ const DeployEverythingBasicStrategy = buildModule("DeployEverythingBasicStrategy crossChainProofValidator, stateLib, smtLib, + poseidonHasher, } = m.useModule(UniversalVerifierModule); const { credentialAtomicQueryMTPV2Validator } = m.useModule( @@ -121,119 +121,10 @@ const DeployEverythingBasicStrategy = buildModule("DeployEverythingBasicStrategy }, ); - const { - universalVerifier: universalVerifier_ManyResponsesPerUserAndRequest, - universalVerifierImplementation: universalVerifier_ManyResponsesPerUserAndRequestImplementation, - verifierLib: verifierLib_ManyResponsesPerUserAndRequest, - } = m.useModule(UniversalVerifier_ManyResponsesPerUserAndRequestModule); - - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [credentialAtomicQueryMTPV2Validator], - { - id: "addValidatorToWhitelist_credentialAtomicQueryMTPV2Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [credentialAtomicQuerySigV2Validator], - { - id: "addValidatorToWhitelist_credentialAtomicQuerySigV2Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [credentialAtomicQueryV3Validator], - { - id: "addValidatorToWhitelist_credentialAtomicQueryV3Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [credentialAtomicQueryV3StableValidator], - { - id: "addValidatorToWhitelist_credentialAtomicQueryV3StableValidator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [linkedMultiQueryValidator], - { - id: "addValidatorToWhitelist_linkedMultiQueryValidator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "addValidatorToWhitelist", - [linkedMultiQueryStableValidator], - { - id: "addValidatorToWhitelist_linkedMultiQueryStableValidator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "setAuthMethod", - [{ authMethod: "ethIdentity", validator: ethIdentityValidator, params: "0x" }], - { - id: "setAuthMethod_ethIdentityValidator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "setAuthMethod", - [{ authMethod: "authV2", validator: authV2Validator, params: "0x" }], - { - id: "setAuthMethod_authV2Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "setAuthMethod", - [{ authMethod: "authV3", validator: authV3Validator, params: "0x" }], - { - id: "setAuthMethod_authV3Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "setAuthMethod", - [{ authMethod: "authV3-8-32", validator: authV3_8_32Validator, params: "0x" }], - { - id: "setAuthMethod_authV3_8_32Validator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - m.call( - universalVerifier_ManyResponsesPerUserAndRequest, - "setAuthMethod", - [{ authMethod: "embeddedAuth", validator: contractsInfo.UNIVERSAL_VERIFIER.unifiedAddress, params: "0x" }], // put some dummy address as validator - { - id: "setAuthMethod_embeddedAuthValidator_ManyResponsesPerUserAndRequest", - from: contractOwner, - }, - ); - return { universalVerifier, universalVerifierImplementation, verifierLib, - universalVerifier_ManyResponsesPerUserAndRequest, - universalVerifier_ManyResponsesPerUserAndRequestImplementation, - verifierLib_ManyResponsesPerUserAndRequest, state, stateImplementation, crossChainProofValidator, @@ -252,6 +143,7 @@ const DeployEverythingBasicStrategy = buildModule("DeployEverythingBasicStrategy authV3_8_32Validator, MCPayment, VCPayment, + poseidonHasher, }; }); diff --git a/ignition/modules/deployEverythingBasicStrategy/identityExample.ts b/ignition/modules/deployEverythingBasicStrategy/identityExample.ts index 97bb26bd4..75acb62c7 100644 --- a/ignition/modules/deployEverythingBasicStrategy/identityExample.ts +++ b/ignition/modules/deployEverythingBasicStrategy/identityExample.ts @@ -1,11 +1,11 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { Poseidon3Module, Poseidon4Module, SmtLibModule } from "./libraries"; +import { Poseidon3Module, Poseidon4Module, SmtLibWithHasherModule } from "./libraries"; import StateModule from "./state"; const IdentityLibModule = buildModule("IdentityLibModule", (m) => { const poseidon3 = m.useModule(Poseidon3Module).poseidon; const poseidon4 = m.useModule(Poseidon4Module).poseidon; - const smtLib = m.useModule(SmtLibModule).smtLib; + const smtLib = m.useModule(SmtLibWithHasherModule).smtLib; const identityLib = m.contract("IdentityLib", [], { libraries: { @@ -27,7 +27,7 @@ const IdentityExampleProxyModule = buildModule("IdentityExampleProxyModule", (m) const { claimBuilder } = m.useModule(ClaimBuilderModule); const { identityLib } = m.useModule(IdentityLibModule); - const state = m.useModule(StateModule).state; + const { state, poseidonHasher } = m.useModule(StateModule); const defaultIdType = m.getParameter("defaultIdType"); const identityExample = m.contract("IdentityExample", [], { @@ -43,7 +43,7 @@ const IdentityExampleProxyModule = buildModule("IdentityExampleProxyModule", (m) id: "identityExampleProxy", }); - m.call(identityExampleProxy, "initialize", [state, defaultIdType], { + m.call(identityExampleProxy, "initialize", [state, defaultIdType, poseidonHasher], { from: proxyAdminOwner, }); diff --git a/ignition/modules/deployEverythingBasicStrategy/identityTreeStore.ts b/ignition/modules/deployEverythingBasicStrategy/identityTreeStore.ts index e6eb11181..eccaadc8a 100644 --- a/ignition/modules/deployEverythingBasicStrategy/identityTreeStore.ts +++ b/ignition/modules/deployEverythingBasicStrategy/identityTreeStore.ts @@ -4,32 +4,31 @@ import { TRANSPARENT_UPGRADEABLE_PROXY_ABI, TRANSPARENT_UPGRADEABLE_PROXY_BYTECODE, } from "../../../helpers/constants"; -import { Poseidon2Module, Poseidon3Module } from "./libraries"; import StateModule from "./state"; +import { PoseidonHasherModule } from "./libraries"; const IdentityTreeStoreImplementationModule = buildModule( "IdentityTreeStoreImplementationModule", (m) => { - const poseidon2 = m.useModule(Poseidon2Module).poseidon; - const poseidon3 = m.useModule(Poseidon3Module).poseidon; + const { poseidonHasher } = m.useModule(PoseidonHasherModule); const state = m.useModule(StateModule).state; - const implementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, [], { - libraries: { - PoseidonUnit2L: poseidon2, - PoseidonUnit3L: poseidon3, - }, - }); - return { implementation, state }; + const implementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, []); + return { implementation, state, poseidonHasher }; }, ); const IdentityTreeStoreProxyModule = buildModule("IdentityTreeStoreProxyModule", (m) => { - const { implementation, state } = m.useModule(IdentityTreeStoreImplementationModule); + const { implementation, state, poseidonHasher } = m.useModule( + IdentityTreeStoreImplementationModule, + ); const proxyAdminOwner = m.getAccount(0); - const initializeData = m.encodeFunctionCall(implementation, "initialize", [state]); + const initializeData = m.encodeFunctionCall(implementation, "initialize", [ + state, + poseidonHasher, + ]); const proxy = m.contract( "TransparentUpgradeableProxy", diff --git a/ignition/modules/deployEverythingBasicStrategy/libraries.ts b/ignition/modules/deployEverythingBasicStrategy/libraries.ts index 653b53272..85c7eef0c 100644 --- a/ignition/modules/deployEverythingBasicStrategy/libraries.ts +++ b/ignition/modules/deployEverythingBasicStrategy/libraries.ts @@ -97,6 +97,26 @@ export const Poseidon6Module = buildModule("Poseidon6Module", (m) => { return { poseidon }; }); +export const PoseidonHasherModule = buildModule("PoseidonHasherModule", (m) => { + const poseidon1Element = m.useModule(Poseidon1Module).poseidon; + const poseidon2Element = m.useModule(Poseidon2Module).poseidon; + const poseidon3Element = m.useModule(Poseidon3Module).poseidon; + + const poseidonHasher = m.contract("PoseidonHasher", [], { + libraries: { + PoseidonUnit1L: poseidon1Element, + PoseidonUnit2L: poseidon2Element, + PoseidonUnit3L: poseidon3Element, + }, + }); + return { poseidonHasher }; +}); + +export const KeccakHasherModule = buildModule("KeccakHasherModule", (m) => { + const keccakHasher = m.contract("Keccak256Hasher", []); + return { keccakHasher }; +}); + export const SmtLibModule = buildModule("SmtLibModule", (m) => { const poseidon2Element = m.useModule(Poseidon2Module).poseidon; const poseidon3Element = m.useModule(Poseidon3Module).poseidon; @@ -110,6 +130,11 @@ export const SmtLibModule = buildModule("SmtLibModule", (m) => { return { smtLib }; }); +export const SmtLibWithHasherModule = buildModule("SmtLibWithHasherModule", (m) => { + const smtLib = m.contract("SmtLib", []); + return { smtLib }; +}); + export const SpongePoseidonModule = buildModule("SpongePoseidonModule", (m) => { const poseidon6Element = m.useModule(Poseidon6Module).poseidon; diff --git a/ignition/modules/deployEverythingBasicStrategy/state.ts b/ignition/modules/deployEverythingBasicStrategy/state.ts index aa7a05e98..5ec072070 100644 --- a/ignition/modules/deployEverythingBasicStrategy/state.ts +++ b/ignition/modules/deployEverythingBasicStrategy/state.ts @@ -1,11 +1,12 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { Poseidon1Module, SmtLibModule } from "./libraries"; +import { SmtLibWithHasherModule } from "./libraries"; import { Groth16VerifierStateTransitionModule } from "./groth16verifiers"; import { contractsInfo, TRANSPARENT_UPGRADEABLE_PROXY_ABI, TRANSPARENT_UPGRADEABLE_PROXY_BYTECODE, } from "../../../helpers/constants"; +import { PoseidonHasherModule } from "./libraries"; export const CrossChainProofValidatorModule = buildModule("CrossChainProofValidatorModule", (m) => { const domainName = "StateInfo"; @@ -27,19 +28,18 @@ const StateLibModule = buildModule("StateLibModule", (m) => { }); const StateImplementationModule = buildModule("StateImplementationModule", (m) => { - const poseidon1 = m.useModule(Poseidon1Module).poseidon; const { groth16VerifierStateTransition: groth16Verifier } = m.useModule( Groth16VerifierStateTransitionModule, ); const { stateLib } = m.useModule(StateLibModule); - const { smtLib } = m.useModule(SmtLibModule); + const { poseidonHasher } = m.useModule(PoseidonHasherModule); + const { smtLib } = m.useModule(SmtLibWithHasherModule); const { crossChainProofValidator } = m.useModule(CrossChainProofValidatorModule); const implementation = m.contract(contractsInfo.STATE.name, [], { libraries: { StateLib: stateLib, SmtLib: smtLib, - PoseidonUnit1L: poseidon1, }, }); @@ -49,12 +49,19 @@ const StateImplementationModule = buildModule("StateImplementationModule", (m) = implementation, stateLib, smtLib, + poseidonHasher, }; }); const StateProxyModule = buildModule("StateProxyModule", (m) => { - const { crossChainProofValidator, groth16Verifier, implementation, stateLib, smtLib } = - m.useModule(StateImplementationModule); + const { + crossChainProofValidator, + groth16Verifier, + implementation, + stateLib, + smtLib, + poseidonHasher, + } = m.useModule(StateImplementationModule); const proxyAdminOwner = m.getAccount(0); @@ -67,6 +74,7 @@ const StateProxyModule = buildModule("StateProxyModule", (m) => { defaultIdType, proxyAdminOwner, crossChainProofValidator, + poseidonHasher, ]); const proxy = m.contract( @@ -81,14 +89,37 @@ const StateProxyModule = buildModule("StateProxyModule", (m) => { [implementation, proxyAdminOwner, initializeData], ); - return { proxy, implementation, crossChainProofValidator, stateLib, smtLib, groth16Verifier }; + return { + proxy, + implementation, + crossChainProofValidator, + stateLib, + smtLib, + groth16Verifier, + poseidonHasher, + }; }); const StateModule = buildModule("StateModule", (m) => { - const { proxy, implementation, crossChainProofValidator, stateLib, smtLib, groth16Verifier } = - m.useModule(StateProxyModule); + const { + proxy, + implementation, + crossChainProofValidator, + stateLib, + smtLib, + groth16Verifier, + poseidonHasher, + } = m.useModule(StateProxyModule); const state = m.contractAt(contractsInfo.STATE.name, proxy); - return { state, implementation, crossChainProofValidator, stateLib, smtLib, groth16Verifier }; + return { + state, + implementation, + crossChainProofValidator, + stateLib, + smtLib, + groth16Verifier, + poseidonHasher, + }; }); export default StateModule; diff --git a/ignition/modules/deployEverythingBasicStrategy/testHelpers.ts b/ignition/modules/deployEverythingBasicStrategy/testHelpers.ts index 13025194b..3c28eb26d 100644 --- a/ignition/modules/deployEverythingBasicStrategy/testHelpers.ts +++ b/ignition/modules/deployEverythingBasicStrategy/testHelpers.ts @@ -1,5 +1,5 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule } from "./libraries"; +import { KeccakHasherModule, PoseidonHasherModule, SmtLibWithHasherModule } from "./libraries"; import { AuthV2ValidatorImplementationModule } from "./authV2Validator"; import StateModule from "./state"; import { @@ -61,14 +61,15 @@ export const AuthValidatorStubModule = buildModule("AuthValidatorStubModule", (m }); export const SmtLibTestWrapperModule = buildModule("SmtLibTestWrapperModule", (m) => { - const smtLib = m.useModule(SmtLibModule).smtLib; + const smtLib = m.useModule(SmtLibWithHasherModule).smtLib; + const poseidonHasher = m.useModule(PoseidonHasherModule).poseidonHasher; const maxDepth = m.getParameter("maxDepth"); if (!maxDepth) { throw new Error(`Failed to get maxDepth`); } - const smtLibTestWrapper = m.contract("SmtLibTestWrapper", [maxDepth], { + const smtLibTestWrapper = m.contract("SmtLibTestWrapper", [maxDepth, poseidonHasher], { libraries: { SmtLib: smtLib, }, @@ -76,10 +77,29 @@ export const SmtLibTestWrapperModule = buildModule("SmtLibTestWrapperModule", (m return { smtLibTestWrapper }; }); +export const SmtLibKeccakTestWrapperModule = buildModule("SmtLibKeccakTestWrapperModule", (m) => { + const smtLib = m.useModule(SmtLibWithHasherModule).smtLib; + const keccakHasher = m.useModule(KeccakHasherModule).keccakHasher; + + const maxDepth = m.getParameter("maxDepth"); + if (!maxDepth) { + throw new Error(`Failed to get maxDepth`); + } + + const smtLibTestWrapper = m.contract("SmtLibTestWrapper", [maxDepth, keccakHasher], { + libraries: { + SmtLib: smtLib, + }, + }); + return { smtLibTestWrapper }; +}); + + export const BinarySearchTestWrapperModule = buildModule("BinarySearchTestWrapperModule", (m) => { - const smtLib = m.useModule(SmtLibModule).smtLib; + const smtLib = m.useModule(SmtLibWithHasherModule).smtLib; + const poseidonHasher = m.useModule(PoseidonHasherModule).poseidonHasher; - const BSWrapper = m.contract("BinarySearchTestWrapper", [], { + const BSWrapper = m.contract("BinarySearchTestWrapper", [poseidonHasher], { libraries: { SmtLib: smtLib, }, diff --git a/ignition/modules/deployEverythingBasicStrategy/universalVerifier.ts b/ignition/modules/deployEverythingBasicStrategy/universalVerifier.ts index c370a542a..103192708 100644 --- a/ignition/modules/deployEverythingBasicStrategy/universalVerifier.ts +++ b/ignition/modules/deployEverythingBasicStrategy/universalVerifier.ts @@ -34,6 +34,7 @@ const UniversalVerifierProxyModule = buildModule("UniversalVerifierProxyModule", crossChainProofValidator, stateLib, smtLib, + poseidonHasher, } = m.useModule(StateModule); const proxyAdminOwner = m.getAccount(0); @@ -62,6 +63,7 @@ const UniversalVerifierProxyModule = buildModule("UniversalVerifierProxyModule", crossChainProofValidator, stateLib, smtLib, + poseidonHasher, }; }); @@ -75,6 +77,7 @@ const UniversalVerifierModule = buildModule("UniversalVerifierModule", (m) => { crossChainProofValidator, stateLib, smtLib, + poseidonHasher, } = m.useModule(UniversalVerifierProxyModule); const universalVerifier = m.contractAt(contractsInfo.UNIVERSAL_VERIFIER.name, proxy); return { @@ -86,6 +89,7 @@ const UniversalVerifierModule = buildModule("UniversalVerifierModule", (m) => { crossChainProofValidator, stateLib, smtLib, + poseidonHasher, }; }); diff --git a/ignition/modules/deployment/deploySystemFinalImplementations.ts b/ignition/modules/deployment/deploySystemFinalImplementations.ts index f74afdf43..3d2d909ab 100644 --- a/ignition/modules/deployment/deploySystemFinalImplementations.ts +++ b/ignition/modules/deployment/deploySystemFinalImplementations.ts @@ -12,12 +12,12 @@ import AuthV2ValidatorModule from "../authV2Validator"; import EthIdentityValidatorModule from "../ethIdentityValidator"; import MCPaymentModule from "../mcPayment"; import VCPaymentModule from "../vcPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; import AuthV3ValidatorModule from "../authV3Validator"; import AuthV3_8_32ValidatorModule from "../authV3_8_32Validator"; import { contractsInfo } from "../../../helpers/constants"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const DeploySystemFianlImplementationsModule = buildModule( "DeploySystemFianlImplementationsModule", diff --git a/ignition/modules/deployment/deploySystemInitialImplementation.ts b/ignition/modules/deployment/deploySystemInitialImplementation.ts index a68fce705..684bad43b 100644 --- a/ignition/modules/deployment/deploySystemInitialImplementation.ts +++ b/ignition/modules/deployment/deploySystemInitialImplementation.ts @@ -5,7 +5,7 @@ import { Poseidon2Module, Poseidon3Module, Poseidon4Module, - SmtLibModule, + SmtLibWithHasherModule, } from "../libraries"; import { StateProxyModule } from "../state"; import { UniversalVerifierProxyModule } from "../universalVerifier"; @@ -33,7 +33,7 @@ const DeploySystemInitialImplementationModule = buildModule( const { poseidon: poseidon3 } = m.useModule(Poseidon3Module); const { poseidon: poseidon4 } = m.useModule(Poseidon4Module); - const { smtLib } = m.useModule(SmtLibModule); + const { smtLib } = m.useModule(SmtLibWithHasherModule); const { newImplementation: newStateImpl } = m.useModule(StateProxyModule); diff --git a/ignition/modules/identityExample.ts b/ignition/modules/identityExample.ts index ea7c581de..1f412717a 100644 --- a/ignition/modules/identityExample.ts +++ b/ignition/modules/identityExample.ts @@ -1,5 +1,11 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { Poseidon3AtModule, Poseidon4AtModule, SmtLibAtModule, StateAtModule } from "./contractsAt"; +import { + Poseidon3AtModule, + Poseidon4AtModule, + PoseidonHasherAtModule, + SmtLibAtModule, + StateAtModule, +} from "./contractsAt"; const IdentityLibModule = buildModule("IdentityLibModule", (m) => { const poseidon3 = m.useModule(Poseidon3AtModule).contract; @@ -42,7 +48,9 @@ const IdentityExampleProxyModule = buildModule("IdentityExampleProxyModule", (m) id: "identityExampleProxy", }); - m.call(identityExampleProxy, "initialize", [state, defaultIdType], { + const { contract: poseidonHasher } = m.useModule(PoseidonHasherAtModule); + + m.call(identityExampleProxy, "initialize", [state, defaultIdType, poseidonHasher], { from: proxyAdminOwner, }); diff --git a/ignition/modules/identityTreeStore.ts b/ignition/modules/identityTreeStore.ts index 9dc7acc37..7df1a7b7e 100644 --- a/ignition/modules/identityTreeStore.ts +++ b/ignition/modules/identityTreeStore.ts @@ -8,8 +8,7 @@ import { Create2AddressAnchorAtModule, IdentityTreeStoreAtModule, IdentityTreeStoreNewImplementationAtModule, - Poseidon2AtModule, - Poseidon3AtModule, + PoseidonHasherAtModule, StateAtModule, } from "./contractsAt"; @@ -46,20 +45,13 @@ const IdentityTreeStoreProxyFirstImplementationModule = buildModule( export const IdentityTreeStoreFinalImplementationModule = buildModule( "IdentityTreeStoreFinalImplementationModule", (m) => { - const poseidon2 = m.useModule(Poseidon2AtModule).contract; - const poseidon3 = m.useModule(Poseidon3AtModule).contract; + const poseidonHasher = m.useModule(PoseidonHasherAtModule).contract; const state = m.useModule(StateAtModule).proxy; - const newImplementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, [], { - libraries: { - PoseidonUnit2L: poseidon2, - PoseidonUnit3L: poseidon3, - }, - }); + const newImplementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, []); return { - poseidon2, - poseidon3, + poseidonHasher, state, newImplementation, }; @@ -68,12 +60,11 @@ export const IdentityTreeStoreFinalImplementationModule = buildModule( export const IdentityTreeStoreProxyModule = buildModule("IdentityTreeStoreProxyModule", (m) => { const { proxy, proxyAdmin } = m.useModule(IdentityTreeStoreProxyFirstImplementationModule); - const { poseidon2, poseidon3, state, newImplementation } = m.useModule( + const { poseidonHasher, state, newImplementation } = m.useModule( IdentityTreeStoreFinalImplementationModule, ); return { - poseidon2, - poseidon3, + poseidonHasher, state, newImplementation, proxyAdmin, @@ -85,22 +76,23 @@ const IdentityTreeStoreProxyFinalImplementationModule = buildModule( "IdentityTreeStoreProxyFinalImplementationModule", (m) => { const { proxy, proxyAdmin } = m.useModule(IdentityTreeStoreAtModule); - const poseidon2 = m.useModule(Poseidon2AtModule).contract; - const poseidon3 = m.useModule(Poseidon3AtModule).contract; + const poseidonHasher = m.useModule(PoseidonHasherAtModule).contract; const state = m.useModule(StateAtModule).proxy; const { contract: newImplementation } = m.useModule(IdentityTreeStoreNewImplementationAtModule); const proxyAdminOwner = m.getAccount(0); - const initializeData = m.encodeFunctionCall(newImplementation, "initialize", [state]); + const initializeData = m.encodeFunctionCall(newImplementation, "initialize", [ + state, + poseidonHasher, + ]); m.call(proxyAdmin, "upgradeAndCall", [proxy, newImplementation, initializeData], { from: proxyAdminOwner, }); return { - poseidon2, - poseidon3, + poseidonHasher, state, newImplementation, proxyAdmin, @@ -110,7 +102,7 @@ const IdentityTreeStoreProxyFinalImplementationModule = buildModule( ); const IdentityTreeStoreModule = buildModule("IdentityTreeStoreModule", (m) => { - const { poseidon2, poseidon3, state, newImplementation, proxyAdmin, proxy } = m.useModule( + const { poseidonHasher, state, newImplementation, proxyAdmin, proxy } = m.useModule( IdentityTreeStoreProxyFinalImplementationModule, ); @@ -118,8 +110,7 @@ const IdentityTreeStoreModule = buildModule("IdentityTreeStoreModule", (m) => { return { identityTreeStore, - poseidon2, - poseidon3, + poseidonHasher, state, newImplementation, proxyAdmin, diff --git a/ignition/modules/libraries.ts b/ignition/modules/libraries.ts index 61a8588fa..fa82e9266 100644 --- a/ignition/modules/libraries.ts +++ b/ignition/modules/libraries.ts @@ -1,6 +1,6 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { poseidonContract } from "circomlibjs"; -import { Poseidon2AtModule, Poseidon3AtModule } from "./contractsAt"; +import { Poseidon1AtModule, Poseidon2AtModule, Poseidon3AtModule } from "./contractsAt"; export const Poseidon1Module = buildModule("Poseidon1Module", (m) => { const nInputs = 1; @@ -98,6 +98,22 @@ export const Poseidon6Module = buildModule("Poseidon6Module", (m) => { return { poseidon }; }); +export const PoseidonHasherModule = buildModule("PoseidonHasherModule", (m) => { + const poseidon1Element = m.useModule(Poseidon1AtModule).contract; + const poseidon2Element = m.useModule(Poseidon2AtModule).contract; + const poseidon3Element = m.useModule(Poseidon3AtModule).contract; + + const poseidonHasher = m.contract("PoseidonHasher", [], { + libraries: { + PoseidonUnit1L: poseidon1Element, + PoseidonUnit2L: poseidon2Element, + PoseidonUnit3L: poseidon3Element, + }, + }); + return { poseidonHasher }; +}); + +// This module is used to deploy the SmtLib contract with the PoseidonHasher library linked to it. export const SmtLibModule = buildModule("SmtLibModule", (m) => { const poseidon2Element = m.useModule(Poseidon2AtModule).contract; const poseidon3Element = m.useModule(Poseidon3AtModule).contract; @@ -111,6 +127,12 @@ export const SmtLibModule = buildModule("SmtLibModule", (m) => { return { smtLib }; }); +// This module is used to deploy the SmtLib contract with hasher contract as param. +export const SmtLibWithHasherModule = buildModule("SmtLibWithHasherModule", (m) => { + const smtLib = m.contract("SmtLib", []); + return { smtLib }; +}); + export const SpongePoseidonModule = buildModule("SpongePoseidonModule", (m) => { const poseidon6Element = m.useModule(Poseidon6Module).poseidon; diff --git a/ignition/modules/state.ts b/ignition/modules/state.ts index 91a474be4..60adfb916 100644 --- a/ignition/modules/state.ts +++ b/ignition/modules/state.ts @@ -9,7 +9,7 @@ import { Create2AddressAnchorAtModule, CrossChainProofValidatorAtModule, Groth16VerifierStateTransitionAtModule, - Poseidon1AtModule, + PoseidonHasherAtModule, SmtLibAtModule, StateAtModule, StateLibAtModule, @@ -66,7 +66,6 @@ export const CrossChainProofValidatorModule = buildModule("CrossChainProofValida }); const StateFinalImplementationModule = buildModule("StateFinalImplementationModule", (m) => { - const poseidon1 = m.useModule(Poseidon1AtModule).contract; const { groth16VerifierStateTransition: groth16Verifier } = m.useModule( Groth16VerifierStateTransitionModule, ); @@ -78,7 +77,6 @@ const StateFinalImplementationModule = buildModule("StateFinalImplementationModu libraries: { StateLib: stateLib, SmtLib: smtLib, - PoseidonUnit1L: poseidon1, }, }); @@ -113,6 +111,7 @@ const StateProxyFinalImplementationModule = buildModule( const { contract: newImplementation } = m.useModule(StateNewImplementationAtModule); const { contract: groth16Verifier } = m.useModule(Groth16VerifierStateTransitionAtModule); const { contract: crossChainProofValidator } = m.useModule(CrossChainProofValidatorAtModule); + const { contract: poseidonHasher } = m.useModule(PoseidonHasherAtModule); const { contract: stateLib } = m.useModule(StateLibAtModule); const proxyAdminOwner = m.getAccount(0); @@ -126,6 +125,7 @@ const StateProxyFinalImplementationModule = buildModule( defaultIdType, proxyAdminOwner, crossChainProofValidator, + poseidonHasher, ]); m.call(proxyAdmin, "upgradeAndCall", [proxy, newImplementation, initializeData], { @@ -139,6 +139,7 @@ const StateProxyFinalImplementationModule = buildModule( groth16Verifier, crossChainProofValidator, stateLib, + poseidonHasher, }; }, ); @@ -148,6 +149,7 @@ const StateModule = buildModule("StateModule", (m) => { crossChainProofValidator, groth16Verifier, stateLib, + poseidonHasher, newImplementation, proxyAdmin, proxy, @@ -160,6 +162,7 @@ const StateModule = buildModule("StateModule", (m) => { crossChainProofValidator, groth16Verifier, stateLib, + poseidonHasher, newImplementation, proxyAdmin, proxy, diff --git a/ignition/modules/upgrades/upgradeIdentityTreeStore.ts b/ignition/modules/upgrades/upgradeIdentityTreeStore.ts index 26795271f..e6009e5f1 100644 --- a/ignition/modules/upgrades/upgradeIdentityTreeStore.ts +++ b/ignition/modules/upgrades/upgradeIdentityTreeStore.ts @@ -1,5 +1,6 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { contractsInfo } from "../../../helpers/constants"; +import { PoseidonHasherModule } from "../libraries"; const version = "V".concat( contractsInfo.IDENTITY_TREE_STORE.version.replaceAll(".", "_").replaceAll("-", "_"), @@ -16,20 +17,12 @@ const UpgradeIdentityTreeStoreModule = buildModule( }); const proxyAdmin = m.contractAt("ProxyAdmin", proxyAdminAddress); - const poseidon2ContractAddress = m.getParameter("poseidon2ContractAddress"); - const poseidon2 = m.contractAt(contractsInfo.POSEIDON_2.name, poseidon2ContractAddress); - const poseidon3ContractAddress = m.getParameter("poseidon3ContractAddress"); - const poseidon3 = m.contractAt(contractsInfo.POSEIDON_3.name, poseidon3ContractAddress); + const newImplementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, []); + const poseidonHasher = m.useModule(PoseidonHasherModule).poseidonHasher; - const newImplementation = m.contract(contractsInfo.IDENTITY_TREE_STORE.name, [], { - libraries: { - PoseidonUnit2L: poseidon2, - PoseidonUnit3L: poseidon3, - }, - }); - - // As we are working with same proxy the storage is already initialized - const initializeData = "0x"; + const initializeData = m.encodeFunctionCall(newImplementation, "initializeHasher", [ + poseidonHasher, + ]); m.call(proxyAdmin, "upgradeAndCall", [proxy, newImplementation, initializeData], { from: proxyAdminOwner, diff --git a/ignition/modules/upgrades/upgradeState.ts b/ignition/modules/upgrades/upgradeState.ts index 3aa77f34b..112dd21c4 100644 --- a/ignition/modules/upgrades/upgradeState.ts +++ b/ignition/modules/upgrades/upgradeState.ts @@ -1,5 +1,6 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { contractsInfo } from "../../../helpers/constants"; +import { PoseidonHasherModule } from "../libraries"; const version = "V".concat(contractsInfo.STATE.version.replaceAll(".", "_").replaceAll("-", "_")); @@ -13,9 +14,6 @@ const UpgradeStateModule = buildModule("UpgradeStateModule".concat(version), (m) }); const proxyAdmin = m.contractAt("ProxyAdmin", proxyAdminAddress); - const poseidon1ContractAddress = m.getParameter("poseidon1ContractAddress"); - const poseidon1 = m.contractAt(contractsInfo.POSEIDON_1.name, poseidon1ContractAddress); - const stateLib = m.contract("StateLib"); const smtLibContractAddress = m.getParameter("smtLibContractAddress"); const smtLib = m.contractAt(contractsInfo.SMT_LIB.name, smtLibContractAddress); @@ -34,14 +32,14 @@ const UpgradeStateModule = buildModule("UpgradeStateModule".concat(version), (m) libraries: { StateLib: stateLib, SmtLib: smtLib, - PoseidonUnit1L: poseidon1, }, }); - // In some old ProxyAdmin versions, the upgradeAndCall function does not accept - // an empty data parameter for initializeData like "0x". - // So we encode a valid function call that does not change the state of the contract. - const initializeData = m.encodeFunctionCall(newImplementation, "VERSION"); + const poseidonHasher = m.useModule(PoseidonHasherModule).poseidonHasher; + + const initializeData = m.encodeFunctionCall(newImplementation, "initializeHasher", [ + poseidonHasher, + ]); m.call(proxyAdmin, "upgradeAndCall", [proxy, newImplementation, initializeData], { from: proxyAdminOwner, diff --git a/scripts/deploy/deployCreate2AddressAnchor.ts b/scripts/deploy/deployCreate2AddressAnchor.ts index f7082d6ca..aa6c75dd7 100644 --- a/scripts/deploy/deployCreate2AddressAnchor.ts +++ b/scripts/deploy/deployCreate2AddressAnchor.ts @@ -1,9 +1,9 @@ import Create2AddressAnchorModule from "../../ignition/modules/create2AddressAnchor"; import { contractsInfo } from "../../helpers/constants"; import { getDeploymentParameters, writeDeploymentParameters } from "../../helpers/helperUtils"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const [signer] = await ethers.getSigners(); diff --git a/scripts/deploy/deployCreateX.ts b/scripts/deploy/deployCreateX.ts index 3b34d704f..981ecb6a2 100644 --- a/scripts/deploy/deployCreateX.ts +++ b/scripts/deploy/deployCreateX.ts @@ -3,9 +3,9 @@ import { // SIGNED_SERIALISED_TRANSACTION_GAS_LIMIT_25000000, SIGNED_SERIALISED_TRANSACTION_GAS_LIMIT_3000000, } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); async function main() { const createXCreatorAddress = "0xeD456e05CaAb11d66C4c797dD6c1D6f9A7F352b5"; diff --git a/scripts/deploy/deployCrossChainProofValidator.ts b/scripts/deploy/deployCrossChainProofValidator.ts index 87ab3ea54..f33d94f5b 100644 --- a/scripts/deploy/deployCrossChainProofValidator.ts +++ b/scripts/deploy/deployCrossChainProofValidator.ts @@ -9,10 +9,10 @@ import { LEGACY_ORACLE_SIGNING_ADDRESS_HARDHAT, LEGACY_ORACLE_SIGNING_ADDRESS_PRODUCTION, } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { CrossChainProofValidatorModule } from "../../ignition"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const chainId = await getChainId(); diff --git a/scripts/deploy/deployEverythingBasicStrategy.ts b/scripts/deploy/deployEverythingBasicStrategy.ts index c18ff3aaa..0904b5d56 100644 --- a/scripts/deploy/deployEverythingBasicStrategy.ts +++ b/scripts/deploy/deployEverythingBasicStrategy.ts @@ -1,9 +1,9 @@ import DeployEverythingBasicStrategy from "../../ignition/modules/deployEverythingBasicStrategy/deployEverythingBasicStrategy"; import { getChainId, getDefaultIdType, verifyContract } from "../../helpers/helperUtils"; import { ORACLE_SIGNING_ADDRESS_PRODUCTION } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); async function main() { const params = { @@ -40,9 +40,7 @@ async function main() { authV3_8_32Validator, MCPayment, VCPayment, - universalVerifier_ManyResponsesPerUserAndRequestImplementation, - universalVerifier_ManyResponsesPerUserAndRequest, - verifierLib_ManyResponsesPerUserAndRequest, + poseidonHasher, } = await ignition.deploy(DeployEverythingBasicStrategy, { parameters: params, deploymentId: `chain-${await getChainId()}-simple-deploy-basic-strategy`, @@ -74,9 +72,7 @@ async function main() { authV3_8_32Validator, MCPayment, VCPayment, - universalVerifier_ManyResponsesPerUserAndRequest, - universalVerifier_ManyResponsesPerUserAndRequestImplementation, - verifierLib_ManyResponsesPerUserAndRequest, + poseidonHasher, ]) { await verifyContract(contract.target, { constructorArgsImplementation: [], diff --git a/scripts/deploy/deployIdentityExample.ts b/scripts/deploy/deployIdentityExample.ts index 2124530c9..2a8dd60ef 100644 --- a/scripts/deploy/deployIdentityExample.ts +++ b/scripts/deploy/deployIdentityExample.ts @@ -1,8 +1,8 @@ import { getDefaultIdType, getDeploymentParameters } from "../../helpers/helperUtils"; import IdentityExampleModule from "../../ignition/modules/identityExample"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const [signer] = await ethers.getSigners(); diff --git a/scripts/deploy/deployIdentityTreeStore.ts b/scripts/deploy/deployIdentityTreeStore.ts index bbb3d50d6..41ef490b7 100644 --- a/scripts/deploy/deployIdentityTreeStore.ts +++ b/scripts/deploy/deployIdentityTreeStore.ts @@ -7,9 +7,9 @@ import { import { contractsInfo } from "../../helpers/constants"; import { IdentityTreeStoreProxyModule } from "../../ignition"; import IdentityTreeStoreModule from "../../ignition/modules/identityTreeStore"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); (async () => { const config = getConfig(); diff --git a/scripts/deploy/deployLibraries.ts b/scripts/deploy/deployLibraries.ts index 75ee9441b..185f848a7 100644 --- a/scripts/deploy/deployLibraries.ts +++ b/scripts/deploy/deployLibraries.ts @@ -10,11 +10,12 @@ import { Poseidon2Module, Poseidon3Module, Poseidon4Module, - SmtLibModule, + PoseidonHasherModule, + SmtLibWithHasherModule, } from "../../ignition"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); @@ -47,7 +48,12 @@ async function main() { paramName: "Poseidon4AtModule", }, { - module: SmtLibModule, + module: PoseidonHasherModule, + name: contractsInfo.POSEIDON_HASHER, + paramName: "PoseidonHasherAtModule", + }, + { + module: SmtLibWithHasherModule, name: contractsInfo.SMT_LIB.name, verificationOpts: contractsInfo.SMT_LIB.verificationOpts, paramName: "SmtLibAtModule", diff --git a/scripts/deploy/deployMCPayment.ts b/scripts/deploy/deployMCPayment.ts index da391a3fe..1ab3f141b 100644 --- a/scripts/deploy/deployMCPayment.ts +++ b/scripts/deploy/deployMCPayment.ts @@ -7,9 +7,9 @@ import { import { contractsInfo } from "../../helpers/constants"; import { MCPaymentProxyModule } from "../../ignition"; import MCPaymentModule from "../../ignition/modules/mcPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployState.ts b/scripts/deploy/deployState.ts index 5e1466e5c..9d433d9a8 100644 --- a/scripts/deploy/deployState.ts +++ b/scripts/deploy/deployState.ts @@ -7,9 +7,9 @@ import { } from "../../helpers/helperUtils"; import { contractsInfo } from "../../helpers/constants"; import StateModule, { StateProxyModule } from "../../ignition/modules/state"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployUniversalVerifier.ts b/scripts/deploy/deployUniversalVerifier.ts index c9e0d5d97..e1be7c187 100644 --- a/scripts/deploy/deployUniversalVerifier.ts +++ b/scripts/deploy/deployUniversalVerifier.ts @@ -8,9 +8,9 @@ import { contractsInfo } from "../../helpers/constants"; import UniversalVerifierModule, { UniversalVerifierProxyModule, } from "../../ignition/modules/universalVerifier"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployVCPayment.ts b/scripts/deploy/deployVCPayment.ts index 8e2b83d72..2bcfc8e0b 100644 --- a/scripts/deploy/deployVCPayment.ts +++ b/scripts/deploy/deployVCPayment.ts @@ -7,9 +7,9 @@ import { import { contractsInfo } from "../../helpers/constants"; import { VCPaymentProxyModule } from "../../ignition"; import VCPaymentModule from "../../ignition/modules/vcPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployValidators.ts b/scripts/deploy/deployValidators.ts index eff0df34c..4764b1c73 100644 --- a/scripts/deploy/deployValidators.ts +++ b/scripts/deploy/deployValidators.ts @@ -35,7 +35,7 @@ import { LinkedMultiQueryStableValidatorAtModule, LinkedMultiQueryValidatorAtModule, } from "../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryV3StableValidatorModule, { CredentialAtomicQueryV3StableValidatorProxyModule, } from "../../ignition/modules/credentialAtomicQueryV3StableValidator"; @@ -49,7 +49,7 @@ import AuthV3_8_32ValidatorModule, { AuthV3_8_32ValidatorProxyModule, } from "../../ignition/modules/authV3_8_32Validator"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployment-step-1/deploySystem.ts b/scripts/deploy/deployment-step-1/deploySystem.ts index a96d27378..768b41ae1 100644 --- a/scripts/deploy/deployment-step-1/deploySystem.ts +++ b/scripts/deploy/deployment-step-1/deploySystem.ts @@ -15,7 +15,8 @@ import { Poseidon2Module, Poseidon3Module, Poseidon4Module, - SmtLibModule, + PoseidonHasherModule, + SmtLibWithHasherModule, VCPaymentProxyModule, } from "../../../ignition"; import { StateProxyModule } from "../../../ignition/modules/state"; @@ -45,18 +46,19 @@ import { Poseidon2AtModule, Poseidon3AtModule, Poseidon4AtModule, + PoseidonHasherAtModule, SmtLibAtModule, StateAtModule, UniversalVerifierAtModule, VCPaymentAtModule, } from "../../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; import { AuthV3ValidatorProxyModule } from "../../../ignition/modules/authV3Validator"; import { AuthV3_8_32ValidatorProxyModule } from "../../../ignition/modules/authV3_8_32Validator"; import { CredentialAtomicQueryV3StableValidatorProxyModule } from "../../../ignition/modules/credentialAtomicQueryV3StableValidator"; import { LinkedMultiQueryStableValidatorProxyModule } from "../../../ignition/modules/linkedMultiQueryStableValidator"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); @@ -139,7 +141,13 @@ async function main() { name: contractsInfo.POSEIDON_4.name, }, { - module: SmtLibModule, + module: PoseidonHasherModule, + moduleAt: PoseidonHasherAtModule, + contractAddress: contractsInfo.POSEIDON_HASHER.unifiedAddress, + name: contractsInfo.POSEIDON_HASHER.name, + }, + { + module: SmtLibWithHasherModule, moduleAt: SmtLibAtModule, contractAddress: contractsInfo.SMT_LIB.unifiedAddress, name: contractsInfo.SMT_LIB.name, diff --git a/scripts/deploy/deployment-step-1/deployUniversalVerifier.ts b/scripts/deploy/deployment-step-1/deployUniversalVerifier.ts index 51283a3fb..4caecd71c 100644 --- a/scripts/deploy/deployment-step-1/deployUniversalVerifier.ts +++ b/scripts/deploy/deployment-step-1/deployUniversalVerifier.ts @@ -14,9 +14,9 @@ import { UniversalVerifierNewImplementationAtModule, VerifierLibAtModule, } from "../../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployment-step-1/deployValidators.ts b/scripts/deploy/deployment-step-1/deployValidators.ts index 15f1b90ac..6398359c9 100644 --- a/scripts/deploy/deployment-step-1/deployValidators.ts +++ b/scripts/deploy/deployment-step-1/deployValidators.ts @@ -12,7 +12,7 @@ import { CredentialAtomicQueryV3ValidatorProxyModule } from "../../../ignition/m import { AuthV2ValidatorProxyModule } from "../../../ignition/modules/authV2Validator"; import { EthIdentityValidatorProxyModule } from "../../../ignition/modules/ethIdentityValidator"; import { LinkedMultiQueryValidatorProxyModule } from "../../../ignition/modules/linkedMultiQueryValidator"; -import { network } from "hardhat"; +import hre from "hardhat"; import { CredentialAtomicQueryV3StableValidatorProxyModule } from "../../../ignition/modules/credentialAtomicQueryV3StableValidator"; import { LinkedMultiQueryStableValidatorProxyModule } from "../../../ignition/modules/linkedMultiQueryStableValidator"; import { AuthV3ValidatorProxyModule } from "../../../ignition/modules/authV3Validator"; @@ -30,7 +30,7 @@ import { LinkedMultiQueryValidatorAtModule, } from "../../../ignition/modules/contractsAt"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployment-step-2/deploySystem.ts b/scripts/deploy/deployment-step-2/deploySystem.ts index d1673031e..3aa5853db 100644 --- a/scripts/deploy/deployment-step-2/deploySystem.ts +++ b/scripts/deploy/deployment-step-2/deploySystem.ts @@ -29,13 +29,13 @@ import { } from "../../../ignition/modules/contractsAt"; import MCPaymentModule from "../../../ignition/modules/mcPayment"; import VCPaymentModule from "../../../ignition/modules/vcPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; import AuthV3ValidatorModule from "../../../ignition/modules/authV3Validator"; import AuthV3_8_32ValidatorModule from "../../../ignition/modules/authV3_8_32Validator"; import LinkedMultiQueryStableValidatorModule from "../../../ignition/modules/linkedMultiQueryStableValidator"; import CredentialAtomicQueryV3StableValidatorModule from "../../../ignition/modules/credentialAtomicQueryV3StableValidator"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployment-step-2/deployUniversalVerifier.ts b/scripts/deploy/deployment-step-2/deployUniversalVerifier.ts index 5c7969f15..b1a0cab6e 100644 --- a/scripts/deploy/deployment-step-2/deployUniversalVerifier.ts +++ b/scripts/deploy/deployment-step-2/deployUniversalVerifier.ts @@ -4,9 +4,9 @@ import { } from "../../../helpers/helperUtils"; import { contractsInfo } from "../../../helpers/constants"; import UniversalVerifierModule from "../../../ignition/modules/universalVerifier"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/deployment-step-2/deployValidators.ts b/scripts/deploy/deployment-step-2/deployValidators.ts index 62415a2d9..bc28de0cb 100644 --- a/scripts/deploy/deployment-step-2/deployValidators.ts +++ b/scripts/deploy/deployment-step-2/deployValidators.ts @@ -18,13 +18,13 @@ import { LinkedMultiQueryStableValidatorAtModule, LinkedMultiQueryValidatorAtModule, } from "../../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryV3StableValidatorModule from "../../../ignition/modules/credentialAtomicQueryV3StableValidator"; import LinkedMultiQueryStableValidatorModule from "../../../ignition/modules/linkedMultiQueryStableValidator"; import AuthV3ValidatorModule from "../../../ignition/modules/authV3Validator"; import AuthV3_8_32ValidatorModule from "../../../ignition/modules/authV3_8_32Validator"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { const config = getConfig(); diff --git a/scripts/deploy/linkValidatorsToUniversalVerifier.ts b/scripts/deploy/linkValidatorsToUniversalVerifier.ts index 5543f96e0..0299bd1f6 100644 --- a/scripts/deploy/linkValidatorsToUniversalVerifier.ts +++ b/scripts/deploy/linkValidatorsToUniversalVerifier.ts @@ -30,9 +30,8 @@ import { LinkedMultiQueryStableValidatorAtModule, LinkedMultiQueryValidatorAtModule, UniversalVerifierAtModule, - UniversalVerifierTestWrapperAtModule_ManyResponsesPerUserAndRequest, } from "../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryV3StableValidatorModule, { CredentialAtomicQueryV3StableValidatorProxyModule, } from "../../ignition/modules/credentialAtomicQueryV3StableValidator"; @@ -47,7 +46,7 @@ import AuthV3_8_32ValidatorModule, { } from "../../ignition/modules/authV3_8_32Validator"; import { transferOwnership } from "../upgrade/helpers/utils"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer @@ -160,33 +159,6 @@ async function main() { universalVerifier = universalVerifierDeployed.proxy; console.log(`Using Universal Verifier at: ${universalVerifier.target}`); - if (impersonate) { - console.log("Impersonating Ledger Account by ownership transfer"); - await transferOwnership(signer, { - proxy: universalVerifierDeployed.proxy, - proxyAdmin: universalVerifierDeployed.proxyAdmin, - }); - } - } else { - parameters = Object.assign(parameters, { - UniversalVerifierTestWrapperAtModule_ManyResponsesPerUserAndRequest: { - proxyAddress: proxyAddress, - proxyAdminAddress: proxyAdminAddress, - }, - }); - const deploymentId = `chain-${await getChainId()}-many-responses-per-user-and-request`; - const universalVerifierDeployed = await ignition.deploy( - UniversalVerifierTestWrapperAtModule_ManyResponsesPerUserAndRequest, - { - strategy: deployStrategy, - defaultSender: await signer.getAddress(), - parameters: parameters, - deploymentId: deploymentId, - }, - ); - universalVerifier = universalVerifierDeployed.proxy; - console.log(`Using Universal Verifier Test Wrapper at: ${universalVerifier.target}`); - if (impersonate) { console.log("Impersonating Ledger Account by ownership transfer"); await transferOwnership(signer, { @@ -228,15 +200,18 @@ async function main() { parameters: parameters, }); if (!(await universalVerifier.authMethodExists(validator.authMethod))) { - const tx = await universalVerifier.setAuthMethod({ - authMethod: validator.authMethod, - validator: validatorDeployed.proxy.target, - params: "0x", - }, { - gasPrice: 10000000, - // initialBaseFeePerGas: 10000000, - // gasLimit: 500000, - }); + const tx = await universalVerifier.setAuthMethod( + { + authMethod: validator.authMethod, + validator: validatorDeployed.proxy.target, + params: "0x", + }, + { + gasPrice: 10000000, + // initialBaseFeePerGas: 10000000, + // gasLimit: 500000, + }, + ); await tx.wait(); console.log( `${validator.name} in address ${validatorDeployed.proxy.target} with authMethod ${validator.authMethod} added to auth methods`, @@ -249,15 +224,18 @@ async function main() { } const authMethodEmbeddedAuth = "embeddedAuth"; if (!(await universalVerifier.authMethodExists(authMethodEmbeddedAuth))) { - const tx = await universalVerifier.setAuthMethod({ - authMethod: authMethodEmbeddedAuth, - validator: contractsInfo.UNIVERSAL_VERIFIER.unifiedAddress, - params: "0x", - }, { - gasPrice: 10000000, - // initialBaseFeePerGas: 10000000, - // gasLimit: 500000, - }); + const tx = await universalVerifier.setAuthMethod( + { + authMethod: authMethodEmbeddedAuth, + validator: contractsInfo.UNIVERSAL_VERIFIER.unifiedAddress, + params: "0x", + }, + { + gasPrice: 10000000, + // initialBaseFeePerGas: 10000000, + // gasLimit: 500000, + }, + ); await tx.wait(); console.log(`${authMethodEmbeddedAuth} added to auth methods`); } else { diff --git a/scripts/maintenance/addValidatorsToUniversalVerifier.ts b/scripts/maintenance/addValidatorsToUniversalVerifier.ts index 41d8e22e1..7fd958804 100644 --- a/scripts/maintenance/addValidatorsToUniversalVerifier.ts +++ b/scripts/maintenance/addValidatorsToUniversalVerifier.ts @@ -2,11 +2,11 @@ import { getChainId, getConfig, Logger } from "../../helpers/helperUtils"; import { contractsInfo } from "../../helpers/constants"; import path from "path"; import fs from "fs"; -import { network } from "hardhat"; +import hre from "hardhat"; const __dirname = path.resolve(); -const { ethers, networkName } = await network.connect(); +const { ethers, networkName } = await hre.network.create(); async function main() { const [signer] = await ethers.getSigners(); diff --git a/scripts/maintenance/checkUniversalVerifierCustomNetwork.ts b/scripts/maintenance/checkUniversalVerifierCustomNetwork.ts index 633aaf63e..5c83e916d 100644 --- a/scripts/maintenance/checkUniversalVerifierCustomNetwork.ts +++ b/scripts/maintenance/checkUniversalVerifierCustomNetwork.ts @@ -6,9 +6,9 @@ import { } from "../upgrade/verifiers/helpers/testVerifier"; import { Contract } from "ethers"; import { core } from "@0xpolygonid/js-sdk"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, networkName } = await network.connect(); +const { ethers, networkName } = await hre.network.create(); // Replace these addresses with the ones deployed in your custom network const universalVerifierAddress = ""; diff --git a/scripts/maintenance/checkUniversalVerifierSingleNetwork.ts b/scripts/maintenance/checkUniversalVerifierSingleNetwork.ts index ca26575f0..d3a9d09e3 100644 --- a/scripts/maintenance/checkUniversalVerifierSingleNetwork.ts +++ b/scripts/maintenance/checkUniversalVerifierSingleNetwork.ts @@ -5,9 +5,9 @@ import { submitZKPResponses_KYCAgeCredential, } from "../upgrade/verifiers/helpers/testVerifier"; import { Contract } from "ethers"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, networkName } = await network.connect(); +const { ethers, networkName } = await hre.network.create(); // Replace these addresses with the ones you want to test const universalVerifierAddress = contractsInfo.UNIVERSAL_VERIFIER.unifiedAddress; diff --git a/scripts/maintenance/computeCreate2Address.ts b/scripts/maintenance/computeCreate2Address.ts index b944969cd..eb756f851 100644 --- a/scripts/maintenance/computeCreate2Address.ts +++ b/scripts/maintenance/computeCreate2Address.ts @@ -1,6 +1,6 @@ -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); async function main() { const byteCode = ""; diff --git a/scripts/maintenance/disableLegacySigningAddressOfCrossChainValidator.ts b/scripts/maintenance/disableLegacySigningAddressOfCrossChainValidator.ts index 28b158612..3e7131878 100644 --- a/scripts/maintenance/disableLegacySigningAddressOfCrossChainValidator.ts +++ b/scripts/maintenance/disableLegacySigningAddressOfCrossChainValidator.ts @@ -1,8 +1,8 @@ import { contractsInfo } from "../../helpers/constants"; import { getStateContractAddress } from "../../helpers/helperUtils"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); async function main() { const stateContractAddress = await getStateContractAddress(); diff --git a/scripts/maintenance/disableProxyContract.ts b/scripts/maintenance/disableProxyContract.ts index b045f43e8..07b1d7b88 100644 --- a/scripts/maintenance/disableProxyContract.ts +++ b/scripts/maintenance/disableProxyContract.ts @@ -1,9 +1,9 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getConfig, getDeploymentParameters } from "../../helpers/helperUtils"; -const { ethers, ignition, networkName } = await network.connect(); +const { ethers, ignition, networkName } = await hre.network.create(); // Put proper contract name here, e.g. contractsInfo.STATE.name const contractName = ""; diff --git a/scripts/maintenance/getContractsAt.ts b/scripts/maintenance/getContractsAt.ts index 35b0f14fa..72b302341 100644 --- a/scripts/maintenance/getContractsAt.ts +++ b/scripts/maintenance/getContractsAt.ts @@ -29,9 +29,9 @@ import { UniversalVerifierAtModule, VCPaymentAtModule, } from "../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); async function main() { // const config = getConfig(); diff --git a/scripts/maintenance/multi-chain/checkIdTypes.ts b/scripts/maintenance/multi-chain/checkIdTypes.ts index d81255c5e..fc97c31c7 100644 --- a/scripts/maintenance/multi-chain/checkIdTypes.ts +++ b/scripts/maintenance/multi-chain/checkIdTypes.ts @@ -6,9 +6,9 @@ import { Logger, } from "../../../helpers/helperUtils"; import { contractsInfo, DEFAULT_MNEMONIC, networks } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const mnemonicWallet = ethers.Wallet.fromPhrase(DEFAULT_MNEMONIC); diff --git a/scripts/maintenance/multi-chain/checkOracleSigningAddress.ts b/scripts/maintenance/multi-chain/checkOracleSigningAddress.ts index 4be6fa3fe..5ce416a09 100644 --- a/scripts/maintenance/multi-chain/checkOracleSigningAddress.ts +++ b/scripts/maintenance/multi-chain/checkOracleSigningAddress.ts @@ -10,9 +10,9 @@ import { LEGACY_ORACLE_SIGNING_ADDRESS_PRODUCTION, ORACLE_SIGNING_ADDRESS_PRODUCTION, } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const mnemonicWallet = ethers.Wallet.fromPhrase(DEFAULT_MNEMONIC); diff --git a/scripts/maintenance/multi-chain/checkUnifiedContracts.ts b/scripts/maintenance/multi-chain/checkUnifiedContracts.ts index 91d566ca2..3b759ee74 100644 --- a/scripts/maintenance/multi-chain/checkUnifiedContracts.ts +++ b/scripts/maintenance/multi-chain/checkUnifiedContracts.ts @@ -6,9 +6,9 @@ import { Logger, } from "../../../helpers/helperUtils"; import { contractsInfo, DEFAULT_MNEMONIC } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const mnemonicWallet = ethers.Wallet.fromPhrase(DEFAULT_MNEMONIC); diff --git a/scripts/maintenance/multi-chain/checkValidatorsUniversalVerifier.ts b/scripts/maintenance/multi-chain/checkValidatorsUniversalVerifier.ts index f42a7efd3..bc3959d2d 100644 --- a/scripts/maintenance/multi-chain/checkValidatorsUniversalVerifier.ts +++ b/scripts/maintenance/multi-chain/checkValidatorsUniversalVerifier.ts @@ -1,14 +1,8 @@ -import { - checkContractVersion, - getProviders, - getStateContractAddress, - isContract, - Logger, -} from "../../../helpers/helperUtils"; +import { getProviders, Logger } from "../../../helpers/helperUtils"; import { contractsInfo, DEFAULT_MNEMONIC } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const mnemonicWallet = ethers.Wallet.fromPhrase(DEFAULT_MNEMONIC); @@ -63,7 +57,7 @@ async function main() { }, { authMethod: "embeddedAuth", - property: "UNIVERSAL_VERIFIER" + property: "UNIVERSAL_VERIFIER", }, ]; @@ -84,12 +78,8 @@ async function main() { } for (const v of authValidators) { - if ( - !(await universalVerifier.authMethodExists(v.authMethod)) - ) { - authValidatorsNotSet.push( - `${v.authMethod} (${contractsInfo[v.property].unifiedAddress})`, - ); + if (!(await universalVerifier.authMethodExists(v.authMethod))) { + authValidatorsNotSet.push(`${v.authMethod} (${contractsInfo[v.property].unifiedAddress})`); } } diff --git a/scripts/maintenance/setOracleSigningAddress.ts b/scripts/maintenance/setOracleSigningAddress.ts index 581a85f1c..4ca494122 100644 --- a/scripts/maintenance/setOracleSigningAddress.ts +++ b/scripts/maintenance/setOracleSigningAddress.ts @@ -1,8 +1,8 @@ import { contractsInfo, ORACLE_SIGNING_ADDRESS_PRODUCTION } from "../../helpers/constants"; import { getStateContractAddress } from "../../helpers/helperUtils"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); async function main() { const oracleSigningAddress = ORACLE_SIGNING_ADDRESS_PRODUCTION; // production signing address diff --git a/scripts/maintenance/setPaymentValue.ts b/scripts/maintenance/setPaymentValue.ts index dc36b0a9e..90c245682 100644 --- a/scripts/maintenance/setPaymentValue.ts +++ b/scripts/maintenance/setPaymentValue.ts @@ -1,10 +1,10 @@ import { DID } from "@iden3/js-iden3-core"; import { byteEncoder, calculateCoreSchemaHash } from "@0xpolygonid/js-sdk"; import { Path } from "@iden3/js-jsonld-merklization"; -import { VCPayment, VCPayment__factory } from "../../typechain-types"; -import { network } from "hardhat"; +import { VCPayment, VCPayment__factory } from "../../typechain"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const ldContextJSONAnimaProofOfUniqueness = `{ "@context": [ diff --git a/scripts/maintenance/setProofRequest.ts b/scripts/maintenance/setProofRequest.ts index 1f96d0693..8f1d729d4 100644 --- a/scripts/maintenance/setProofRequest.ts +++ b/scripts/maintenance/setProofRequest.ts @@ -6,9 +6,9 @@ import { contractsInfo } from "../../helpers/constants"; import { Hex } from "@iden3/js-crypto"; import { getChainId } from "../../helpers/helperUtils"; import { calculateRequestID } from "../../test/utils/id-calculation-utils"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, networkName } = await network.connect(); +const { ethers, networkName } = await hre.network.create(); export function getAuthV2RequestId(): number { const circuitHash = ethers.keccak256(byteEncoder.encode(CircuitId.AuthV2)); diff --git a/scripts/maintenance/setSupportedIdTypes.ts b/scripts/maintenance/setSupportedIdTypes.ts index d0bc9f885..8ba0b1dd9 100644 --- a/scripts/maintenance/setSupportedIdTypes.ts +++ b/scripts/maintenance/setSupportedIdTypes.ts @@ -1,9 +1,9 @@ import { getChainId, getStateContractAddress } from "../../helpers/helperUtils"; import { contractsInfo, networks } from "../../helpers/constants"; import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); async function main() { const stateContractAddress = await getStateContractAddress(); diff --git a/scripts/upgrade/helpers/utils.ts b/scripts/upgrade/helpers/utils.ts index a3e1948a5..e7f6e0ac0 100644 --- a/scripts/upgrade/helpers/utils.ts +++ b/scripts/upgrade/helpers/utils.ts @@ -1,7 +1,7 @@ import { Signer } from "ethers"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); export async function transferOwnership(signer: Signer, contractAt: any) { const maxFeePerGas = 250000000000; @@ -28,9 +28,35 @@ export async function transferOwnership(signer: Signer, contractAt: any) { .transferOwnership(await signer.getAddress()); await tx1.wait(); - const tx2 = await contractAt.proxy.connect(proxyOwnerSigner).transferOwnership(await signer.getAddress()); + const tx2 = await contractAt.proxy + .connect(proxyOwnerSigner) + .transferOwnership(await signer.getAddress()); await tx2.wait(); const tx3 = await contractAt.proxy.connect(signer).acceptOwnership(); await tx3.wait(); } + +export async function transferProxyAdminOwnership(signer: Signer, contractAt: any) { + const maxFeePerGas = 250000000000; + const etherAmount = ethers.parseEther("10"); + + console.log("Proxy Admin owner: ", await contractAt.proxyAdmin.owner()); + console.log("Transferring ownership of Proxy Admin to: ", await signer.getAddress()); + + const proxyAdminOwnerSigner = await ethers.getImpersonatedSigner( + await contractAt.proxyAdmin.owner(), + ); + + // transfer some ether to the proxy admin owner and state owner to pay for the transaction fees + await signer.sendTransaction({ + to: proxyAdminOwnerSigner.address, + value: etherAmount, + maxFeePerGas, + }); + + const tx1 = await contractAt.proxyAdmin + .connect(proxyAdminOwnerSigner) + .transferOwnership(await signer.getAddress()); + await tx1.wait(); +} diff --git a/scripts/upgrade/identitytreestore/identitytreestore-upgrade.ts b/scripts/upgrade/identitytreestore/identitytreestore-upgrade.ts index 7f69a21dd..ff2e946b3 100644 --- a/scripts/upgrade/identitytreestore/identitytreestore-upgrade.ts +++ b/scripts/upgrade/identitytreestore/identitytreestore-upgrade.ts @@ -6,11 +6,11 @@ import { writeDeploymentParameters, } from "../../../helpers/helperUtils"; import { contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import UpgradeIdentityTreeStoreModule from "../../../ignition/modules/upgrades/upgradeIdentityTreeStore"; -import { transferOwnership } from "../helpers/utils"; +import { transferProxyAdminOwnership } from "../helpers/utils"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer @@ -39,7 +39,9 @@ async function main() { ); if (upgraded) { - console.log(`Contract is already upgraded to version ${contractsInfo.IDENTITY_TREE_STORE.version}`); + console.log( + `Contract is already upgraded to version ${contractsInfo.IDENTITY_TREE_STORE.version}`, + ); return; } else { console.log( @@ -58,30 +60,31 @@ async function main() { if (impersonate) { console.log("Impersonating Ledger Account by ownership transfer"); - await transferOwnership(signer, { proxy: proxyAt, proxyAdmin: proxyAdminAt }); + await transferProxyAdminOwnership(signer, { proxy: proxyAt, proxyAdmin: proxyAdminAt }); } const identityTreeStoreContract = proxyAt; console.log("Version before:", await identityTreeStoreContract.VERSION()); - const version = "V".concat(contractsInfo.IDENTITY_TREE_STORE.version.replaceAll(".", "_").replaceAll("-", "_")); + const version = "V".concat( + contractsInfo.IDENTITY_TREE_STORE.version.replaceAll(".", "_").replaceAll("-", "_"), + ); parameters["UpgradeIdentityTreeStoreModule".concat(version)] = { proxyAddress: parameters.IdentityTreeStoreAtModule.proxyAddress, proxyAdminAddress: parameters.IdentityTreeStoreAtModule.proxyAdminAddress, - poseidon2ContractAddress: parameters.Poseidon2AtModule.contractAddress, - poseidon3ContractAddress: parameters.Poseidon3AtModule.contractAddress, }; // **** Upgrade IdentityTreeStore **** - - const { newImplementation, identityTreeStore, proxy, proxyAdmin } = - await ignition.deploy(UpgradeIdentityTreeStoreModule, { + const { newImplementation, identityTreeStore, proxy, proxyAdmin } = await ignition.deploy( + UpgradeIdentityTreeStoreModule, + { defaultSender: signer.address, parameters: parameters, deploymentId: deploymentId, - }); + }, + ); parameters.IdentityTreeStoreAtModule = { proxyAddress: proxy.target, @@ -93,6 +96,7 @@ async function main() { // ********************************** console.log("Version after:", await identityTreeStore.VERSION()); + console.log("State Address after:", await identityTreeStore.getStateAddress()); await verifyContract( await identityTreeStore.getAddress(), diff --git a/scripts/upgrade/payments/mcPayment-upgrade.ts b/scripts/upgrade/payments/mcPayment-upgrade.ts index acacfc7dc..a1bd013d6 100644 --- a/scripts/upgrade/payments/mcPayment-upgrade.ts +++ b/scripts/upgrade/payments/mcPayment-upgrade.ts @@ -9,9 +9,9 @@ import { import { contractsInfo } from "../../../helpers/constants"; import { transferOwnership } from "../helpers/utils"; import UpgradeMCPaymentModule from "../../../ignition/modules/upgrades/upgradeMCPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer diff --git a/scripts/upgrade/payments/vcPayment-upgrade.ts b/scripts/upgrade/payments/vcPayment-upgrade.ts index c914ef54f..83810f30d 100644 --- a/scripts/upgrade/payments/vcPayment-upgrade.ts +++ b/scripts/upgrade/payments/vcPayment-upgrade.ts @@ -9,9 +9,9 @@ import { import { contractsInfo } from "../../../helpers/constants"; import { transferOwnership } from "../helpers/utils"; import UpgradeVCPaymentModule from "../../../ignition/modules/upgrades/upgradeVCPayment"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer diff --git a/scripts/upgrade/state/state-upgrade.ts b/scripts/upgrade/state/state-upgrade.ts index 8ab8af575..89dfe4abc 100644 --- a/scripts/upgrade/state/state-upgrade.ts +++ b/scripts/upgrade/state/state-upgrade.ts @@ -1,4 +1,4 @@ -import { network } from "hardhat"; +import hre from "hardhat"; import { expect } from "chai"; // abi of contract that will be upgraded import { checkContractVersion, @@ -12,7 +12,7 @@ import { contractsInfo } from "../../../helpers/constants"; import UpgradeStateModule from "../../../ignition/modules/upgrades/upgradeState"; import { transferOwnership } from "../helpers/utils"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer @@ -68,6 +68,7 @@ async function main() { const defaultIdTypeBefore = await stateContract.getDefaultIdType(); const stateOwnerAddressBefore = await stateContract.owner(); + const gistRootBefore = await stateContract.getGISTRoot(); const version = "V".concat(contractsInfo.STATE.version.replaceAll(".", "_").replaceAll("-", "_")); parameters["UpgradeStateModule".concat(version)] = { @@ -75,7 +76,6 @@ async function main() { proxyAdminAddress: parameters.StateAtModule.proxyAdminAddress, oracleSigningAddress: parameters.CrossChainProofValidatorModule.oracleSigningAddress, smtLibContractAddress: parameters.SmtLibAtModule.contractAddress, - poseidon1ContractAddress: parameters.Poseidon1AtModule.contractAddress, }; // **** Upgrade State **** @@ -116,9 +116,11 @@ async function main() { const defaultIdTypeAfter = await state.getDefaultIdType(); const stateOwnerAddressAfter = await state.owner(); + const gistRootAfter = await state.getGISTRoot(); expect(defaultIdTypeAfter).to.equal(defaultIdTypeBefore); expect(stateOwnerAddressAfter).to.equal(stateOwnerAddressBefore); + expect(gistRootAfter).to.equal(gistRootBefore); const tx1 = await state.setCrossChainProofValidator(crossChainProofValidator.target); await tx1.wait(); diff --git a/scripts/upgrade/validators/validators-upgrade.ts b/scripts/upgrade/validators/validators-upgrade.ts index 5491eb043..e3e9caf4b 100644 --- a/scripts/upgrade/validators/validators-upgrade.ts +++ b/scripts/upgrade/validators/validators-upgrade.ts @@ -13,13 +13,13 @@ import UpgradeAuthV2ValidatorModule from "../../../ignition/modules/upgrades/upg import UpgradeEthIdentityValidatorModule from "../../../ignition/modules/upgrades/upgradeEthIdentityValidator"; import UpgradeLinkedMultiQueryValidatorModule from "../../../ignition/modules/upgrades/upgradeLinkedMultiQuery"; import { transferOwnership } from "../helpers/utils"; -import { network } from "hardhat"; +import hre from "hardhat"; import UpgradeAuthV3ValidatorModule from "../../../ignition/modules/upgrades/upgradeAuthV3Validator"; import UpgradeAuthV3_8_32ValidatorModule from "../../../ignition/modules/upgrades/upgradeAuthV3_8_32Validator"; import UpgradeCredentialAtomicQueryV3StableValidatorModule from "../../../ignition/modules/upgrades/upgradeCredentialAtomicQueryV3StableValidator"; import UpgradeLinkedMultiQueryStableValidatorModule from "../../../ignition/modules/upgrades/upgradeLinkedMultiQueryStable"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer diff --git a/scripts/upgrade/verifiers/embedded-verifier-upgrade.ts b/scripts/upgrade/verifiers/embedded-verifier-upgrade.ts index 914b427b1..564b48ab5 100644 --- a/scripts/upgrade/verifiers/embedded-verifier-upgrade.ts +++ b/scripts/upgrade/verifiers/embedded-verifier-upgrade.ts @@ -12,9 +12,9 @@ import { contractsInfo } from "../../../helpers/constants"; import { buildModule } from "@nomicfoundation/ignition-core"; import { Contract } from "ethers"; import { StateAtModule } from "../../../ignition/modules/contractsAt"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); const embeddedVerifierName = ""; const embeddedVerifierAddress = ""; diff --git a/scripts/upgrade/verifiers/helpers/testVerifier.ts b/scripts/upgrade/verifiers/helpers/testVerifier.ts index 83bf6b5ee..9096a7c10 100644 --- a/scripts/upgrade/verifiers/helpers/testVerifier.ts +++ b/scripts/upgrade/verifiers/helpers/testVerifier.ts @@ -41,9 +41,9 @@ import { getChainId } from "../../../../helpers/helperUtils"; import { calculateRequestID } from "../../../../test/utils/id-calculation-utils"; import * as uuid from "uuid"; import { Groth16VerifierType } from "../../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, networkName } = await network.connect(); +const { ethers, networkName } = await hre.network.create(); const rhsUrl = "https://rhs-staging.polygonid.me"; let nullifierSessionId = 11837235; diff --git a/scripts/upgrade/verifiers/universal-verifier-upgrade.ts b/scripts/upgrade/verifiers/universal-verifier-upgrade.ts index e3eed39ca..a64577e73 100644 --- a/scripts/upgrade/verifiers/universal-verifier-upgrade.ts +++ b/scripts/upgrade/verifiers/universal-verifier-upgrade.ts @@ -10,9 +10,9 @@ import { import { contractsInfo } from "../../../helpers/constants"; import UpgradeUniversalVerifierModule from "../../../ignition/modules/upgrades/upgradeUniversalVerifier"; import { transferOwnership } from "../helpers/utils"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // If you want to use impersonation, set the impersonate variable to true // With ignition we can't use impersonation, so we need to transfer ownership to the signer diff --git a/test/IdentityTreeStore/IdentityTreeStore.test.ts b/test/IdentityTreeStore/IdentityTreeStore.test.ts index 1b58e9207..8c9cf8dc4 100644 --- a/test/IdentityTreeStore/IdentityTreeStore.test.ts +++ b/test/IdentityTreeStore/IdentityTreeStore.test.ts @@ -2,13 +2,13 @@ import { expect } from "chai"; import { poseidon } from "@iden3/js-crypto"; import { Contract } from "ethers"; import { publishStateWithStubProof } from "../utils/state-utils"; -import { network } from "hardhat"; +import hre from "hardhat"; import IdentityTreeStoreModule from "../../ignition/modules/deployEverythingBasicStrategy/identityTreeStore"; import { getChainId } from "../../helpers/helperUtils"; import { chainIdInfoMap } from "../../helpers/constants"; import { Groth16VerifierStubModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("IdentityTreeStore", function () { let identityTreeStore, stateContract: Contract; diff --git a/test/check-unified-addresses.test.ts b/test/check-unified-addresses.test.ts index 38632422a..15f9256bb 100644 --- a/test/check-unified-addresses.test.ts +++ b/test/check-unified-addresses.test.ts @@ -1,10 +1,10 @@ import { contractsInfo } from "../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { isContract, Logger } from "../helpers/helperUtils"; import Create2AddressAnchorModule from "../ignition/modules/create2AddressAnchor"; import { GeneralProxyModule } from "./utils/unified-contracts-utils"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); // Replace here with your own proxy admin owner address const proxyAdminOwnerAddress = "0xAe15d2023A76174a940cbb2b7F44012C728B9d74"; diff --git a/test/cross-chain/cross-chain-proof-validator.test.ts b/test/cross-chain/cross-chain-proof-validator.test.ts index 6173290ad..873eb8498 100644 --- a/test/cross-chain/cross-chain-proof-validator.test.ts +++ b/test/cross-chain/cross-chain-proof-validator.test.ts @@ -6,12 +6,12 @@ import { } from "../utils/packData"; import { expect } from "chai"; import { Contract, ZeroAddress } from "ethers"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { chainIdInfoMap } from "../../helpers/constants"; import { CrossChainProofValidatorModule } from "../../ignition"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("Process cross-chain proof", function () { let crossChainProofValidator: Contract; diff --git a/test/disable-proxy.test.ts b/test/disable-proxy.test.ts index ad82d454f..9642520f9 100644 --- a/test/disable-proxy.test.ts +++ b/test/disable-proxy.test.ts @@ -1,5 +1,5 @@ import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { Groth16VerifierStubModule } from "../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { @@ -7,7 +7,7 @@ import { TRANSPARENT_UPGRADEABLE_PROXY_BYTECODE, } from "../helpers/constants"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); // dummy proof const d = [ diff --git a/test/genesisUtils/genesisUtils.test.ts b/test/genesisUtils/genesisUtils.test.ts index 7a266af49..3b93596be 100644 --- a/test/genesisUtils/genesisUtils.test.ts +++ b/test/genesisUtils/genesisUtils.test.ts @@ -1,9 +1,9 @@ import { Blockchain, buildDIDType, DidMethod, Id, NetworkId } from "@iden3/js-iden3-core"; import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { GenesisUtilsWrapperModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); let guWrpr; const testVectors = [ diff --git a/test/get-own-unified-addresses.test.ts b/test/get-own-unified-addresses.test.ts index c73bf37d7..dc1029e52 100644 --- a/test/get-own-unified-addresses.test.ts +++ b/test/get-own-unified-addresses.test.ts @@ -1,10 +1,10 @@ -import { network } from "hardhat"; +import hre from "hardhat"; import { contractsInfo } from "../helpers/constants"; import { isContract, Logger } from "../helpers/helperUtils"; import Create2AddressAnchorModule from "../ignition/modules/create2AddressAnchor"; import { GeneralProxyModule } from "./utils/unified-contracts-utils"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); // TODO: Replace here with your own proxy admin owner address const proxyAdminOwnerAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; diff --git a/test/integration-tests/integration-verifier.test.ts b/test/integration-tests/integration-verifier.test.ts index 2ccbb4769..f0520fdae 100644 --- a/test/integration-tests/integration-verifier.test.ts +++ b/test/integration-tests/integration-verifier.test.ts @@ -1,4 +1,4 @@ -import { network } from "hardhat"; +import hre from "hardhat"; import { prepareInputs } from "../utils/state-utils"; import authV2ProofJson from "./data/user_genesis_authV2.json"; import authV3ProofJson from "./data/user_genesis_authV3.json"; @@ -20,7 +20,7 @@ import AuthV2ValidatorModule from "../../ignition/modules/deployEverythingBasicS import LinkedMultiQueryValidatorModule from "../../ignition/modules/deployEverythingBasicStrategy/linkedMultiQueryValidator"; import AuthV3ValidatorModule from "../../ignition/modules/deployEverythingBasicStrategy/authV3Validator"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("Verifier Integration test", async function () { let verifier, verifierLib, v3Validator, lmqValidator; diff --git a/test/onchain-identity/claim-builder.test.ts b/test/onchain-identity/claim-builder.test.ts index 3a03383f0..9e578ca3e 100644 --- a/test/onchain-identity/claim-builder.test.ts +++ b/test/onchain-identity/claim-builder.test.ts @@ -1,9 +1,9 @@ import { expect } from "chai"; import claimDataJson from "./vectorsGen/data/claimBuilderData.json"; -import { network } from "hardhat"; +import hre from "hardhat"; import { ClaimBuilderWrapperModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); describe("Claim builder tests", function () { let identity; diff --git a/test/onchain-identity/onchain-identity.test.ts b/test/onchain-identity/onchain-identity.test.ts index 564b3cfb2..fbb68f38e 100644 --- a/test/onchain-identity/onchain-identity.test.ts +++ b/test/onchain-identity/onchain-identity.test.ts @@ -1,11 +1,11 @@ import { expect } from "chai"; import { getChainId } from "../../helpers/helperUtils"; import { chainIdInfoMap } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import IdentityExampleModule from "../../ignition/modules/deployEverythingBasicStrategy/identityExample"; import { GenesisUtilsWrapperModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); describe("Next tests reproduce identity life cycle", function () { this.timeout(10000); diff --git a/test/payment/mc-payment.test.ts b/test/payment/mc-payment.test.ts index c9d31d628..67ca9485a 100644 --- a/test/payment/mc-payment.test.ts +++ b/test/payment/mc-payment.test.ts @@ -1,9 +1,9 @@ -import { network } from "hardhat"; +import hre from "hardhat"; import { expect } from "chai"; import { type Signer } from "ethers"; import MCPaymentModule from "../../ignition/modules/deployEverythingBasicStrategy/mcPayment"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("MC Payment Contract", () => { let payment; diff --git a/test/payment/vc-payment.test.ts b/test/payment/vc-payment.test.ts index 786341edc..a35e05b5f 100644 --- a/test/payment/vc-payment.test.ts +++ b/test/payment/vc-payment.test.ts @@ -1,10 +1,10 @@ import { Hex } from "@iden3/js-crypto"; import { DID, SchemaHash } from "@iden3/js-iden3-core"; -import { network } from "hardhat"; +import hre from "hardhat"; import { expect } from "chai"; import VCPaymentModule from "../../ignition/modules/deployEverythingBasicStrategy/vcPayment"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("VC Payment Contract", () => { let payment; diff --git a/test/poseidon/poseidon.test.ts b/test/poseidon/poseidon.test.ts index 300268028..9ece540af 100644 --- a/test/poseidon/poseidon.test.ts +++ b/test/poseidon/poseidon.test.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { PoseidonFacadeModule } from "../../ignition/modules/deployEverythingBasicStrategy/libraries"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); describe("poseidon", () => { let poseidonFacade; diff --git a/test/primitiveUtils/primitiveUtils.test.ts b/test/primitiveUtils/primitiveUtils.test.ts index 6ccc4d4df..5418af52b 100644 --- a/test/primitiveUtils/primitiveUtils.test.ts +++ b/test/primitiveUtils/primitiveUtils.test.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { PrimitiveTypeUtilsWrapperModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ignition } = await network.connect(); +const { ignition } = await hre.network.create(); let utilsWrapper; diff --git a/test/reverseHash/reverseHash.test.ts b/test/reverseHash/reverseHash.test.ts index 7ecd92ae0..41e15bfbe 100644 --- a/test/reverseHash/reverseHash.test.ts +++ b/test/reverseHash/reverseHash.test.ts @@ -1,9 +1,9 @@ -import { network } from "hardhat"; +import hre from "hardhat"; import { expect } from "chai"; import { poseidon } from "@iden3/js-crypto"; import { Poseidon2Module, Poseidon3Module } from "../../ignition/modules/deployEverythingBasicStrategy/libraries"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); describe("ReverseHashWrapper", function () { let reverseHashWrapper; diff --git a/test/smtLib/smtLib.keccak.test.ts b/test/smtLib/smtLib.keccak.test.ts new file mode 100644 index 000000000..9e3250b01 --- /dev/null +++ b/test/smtLib/smtLib.keccak.test.ts @@ -0,0 +1,1926 @@ +import { expect } from "chai"; +import hre from "hardhat"; +import { addLeaf, type FixedArray, genMaxBinaryNumber, type MtpProof } from "../utils/state-utils"; +import { + BinarySearchTestWrapperModule, + SmtLibKeccakTestWrapperModule, +} from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; +import { SMT_MAX_DEPTH } from "../../helpers/constants"; + +const { ethers, networkHelpers, ignition, provider } = await hre.network.create(); + +type ParamsProofByHistoricalRoot = { + index: number | bigint | string; + historicalRoot: number | string; +}; +type ParamsProofByBlock = { index: number | bigint | string; blockNumber: number | string }; +type ParamsProofByTime = { index: number | bigint | string; timestamp: number | string }; + +type ParamsProof = + | number + | bigint + | string + | ParamsProofByHistoricalRoot + | ParamsProofByBlock + | ParamsProofByTime + | undefined; + +type TestCaseMTPProof = { + leavesToInsert: { i: number | bigint | string; v: number | bigint | string; error?: string }[]; + paramsToGetProof?: ParamsProof; + expectedProof?: MtpProof; + [key: string]: any; +}; + +type RootEntry = { + timestamp: number; + block: number; + root: number; +}; + +type TestCaseRootHistory = { + description: string; + timestamp: number; + blockNumber: number; + expectedRoot: number; + [key: string]: any; +}; + +async function deployContractsFixture() { + const params = { + SmtLibKeccakTestWrapperModule: { + maxDepth: SMT_MAX_DEPTH, + }, + }; + const smtLibTestWrapper = ( + await ignition.deploy(SmtLibKeccakTestWrapperModule, { parameters: params }) + ).smtLibTestWrapper; + return { smtLibTestWrapper }; +} + +describe("Merkle tree proofs of SMT (Keccak hasher)", () => { + let smt; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + describe("SMT existence proof", () => { + describe("keys 4 (100), 2 (010)", () => { + const testCasesExistence: TestCaseMTPProof[] = [ + { + description: "add 1 leaf and generate the proof for it", + leavesToInsert: [{ i: 4, v: 444 }], + paramsToGetProof: 4, + expectedProof: { + root: "22958977272721485097221938248834413051866334275107448764221195104671274302803", + existence: true, + siblings: Array(64).fill(0) as FixedArray, + index: 4, + value: 444, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: "add 2 leaves (depth = 2) and generate the proof of the second one", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + ], + paramsToGetProof: 2, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: true, + siblings: [ + "0", + "22958977272721485097221938248834413051866334275107448764221195104671274302803", + ].concat(Array(62).fill(0)) as FixedArray, + index: 2, + value: 222, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2) update 2nd one and generate the proof of the first one", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: 4, + expectedProof: { + root: "16396604133323839338919891555968694657750322967047028825382984961917414135680", + existence: true, + siblings: [ + "0", + "106205607234728094801824820546945464662359795328028380050005012207955127231073", + ].concat(Array(62).fill(0)) as FixedArray, + index: 4, + value: 444, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the second one", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: 2, + expectedProof: { + root: "16396604133323839338919891555968694657750322967047028825382984961917414135680", + existence: true, + siblings: [ + "0", + "22958977272721485097221938248834413051866334275107448764221195104671274302803", + ].concat(Array(62).fill(0)) as FixedArray, + index: 2, + value: 223, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the first one for the previous root state", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: { + index: 2, + historicalRoot: + "6271825503835002167390262846571952849048843004006797408985626104559410349007", + }, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: true, + siblings: [ + "0", + "22958977272721485097221938248834413051866334275107448764221195104671274302803", + ].concat(Array(62).fill(0)) as FixedArray, + index: 2, + value: 222, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the second one for the previous root state", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: { + index: 4, + historicalRoot: + "6271825503835002167390262846571952849048843004006797408985626104559410349007", + }, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: true, + siblings: [ + "0", + "78830676469618643418259161717399883581838239495817397573365812847452816685443", + ].concat(Array(62).fill(0)) as FixedArray, + index: 4, + value: 444, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + ]; + + for (const testCase of testCasesExistence) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("keys 3 (011), 7 (111)", () => { + const testCasesExistence: TestCaseMTPProof[] = [ + { + description: "add 1 leaf and generate the proof for it", + leavesToInsert: [{ i: 3, v: 333 }], + paramsToGetProof: 3, + expectedProof: { + root: "33418405206138732565596445817172696059570130655374283008161682599505407512429", + existence: true, + siblings: Array(64).fill(0) as FixedArray, + index: "3", + value: "333", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: "add 2 leaves (depth = 2) and generate the proof of the second one", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + ], + paramsToGetProof: 7, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: true, + siblings: [ + "0", + "0", + "33418405206138732565596445817172696059570130655374283008161682599505407512429", + ].concat(Array(61).fill(0)) as FixedArray, + index: "7", + value: "777", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2) update 2nd one and generate the proof of the first one", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: 3, + expectedProof: { + root: "99343494309985223004431568049537972373969240419555846106086358328736705856273", + existence: true, + siblings: [ + "0", + "0", + "112313283557488934319533843029412977758210563652664683830759028786502416187169", + ].concat(Array(61).fill(0)) as FixedArray, + index: "3", + value: "333", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the second one", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: 7, + expectedProof: { + root: "99343494309985223004431568049537972373969240419555846106086358328736705856273", + existence: true, + siblings: [ + "0", + "0", + "33418405206138732565596445817172696059570130655374283008161682599505407512429", + ].concat(Array(61).fill(0)) as FixedArray, + index: "7", + value: "778", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the first one for the previous root state", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: { + index: 3, + historicalRoot: + "48360753217216801628383385897610760751395521399060591925309269460841854478880", + }, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: true, + siblings: [ + "0", + "0", + "50296473614243876656937981110997905853887938112796700896791687746944667051313", + ].concat(Array(61).fill(0)) as FixedArray, + index: "3", + value: "333", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2) update the 2nd leaf and generate the proof of the second one for the previous root state", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: { + index: 7, + historicalRoot: + "48360753217216801628383385897610760751395521399060591925309269460841854478880", + }, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: true, + siblings: [ + "0", + "0", + "33418405206138732565596445817172696059570130655374283008161682599505407512429", + ].concat(Array(61).fill(0)) as FixedArray, + index: "7", + value: "777", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + ]; + + for (const testCase of testCasesExistence) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("big keys and values", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "add 10 big keys and values and generate the proof of the last one", + leavesToInsert: [ + { + i: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + v: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + }, + { + i: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + v: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + }, + { + i: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + v: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + }, + { + i: "889985217497699235766882779777015930299841231159370680230752238312340113600", + v: "889985217497699235766882779777015930299841231159370680230752238312340113600", + }, + { + i: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + v: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + }, + { + i: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + v: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + }, + { + i: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + v: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + }, + { + i: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + v: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + }, + { + i: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + v: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + }, + { + i: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + v: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + }, + ], + paramsToGetProof: + "2254139687286372760549210172096572575821880629072851135313477335313002867070", + expectedProof: { + root: "60007161943983486146906500160381123178622458462493617850821425381979612616956", + existence: true, + siblings: [ + "11842043060776711430669533915732787960772621560012996635304388961537219372006", + "58180682306773137243712131495542060329763268994690040321062652108869108341898", + "94191217124907006392892149230646386351460750107001924913640299034519044572186", + "0", + "68634643421786404149040398078509254181052706327147925186290660391175330864565", + ].concat(Array(59).fill(0)) as FixedArray, + index: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + value: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + }); + + describe("SMT non existence proof", () => { + describe("keys 4 (100), 2 (010)", () => { + const testCasesNonExistence: TestCaseMTPProof[] = [ + { + description: "add 1 leaf and generate a proof on non-existing leaf", + leavesToInsert: [{ i: 4, v: 444 }], + paramsToGetProof: 2, + expectedProof: { + root: "22958977272721485097221938248834413051866334275107448764221195104671274302803", + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: 2, + value: 444, + auxExistence: true, + auxIndex: 4, + auxValue: 444, + }, + }, + { + description: + "add 2 leaves (depth = 2) and generate proof on non-existing leaf WITH aux node", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + ], + paramsToGetProof: 6, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: false, + siblings: [ + "0", + "22958977272721485097221938248834413051866334275107448764221195104671274302803", + ].concat(Array(62).fill(0)) as FixedArray, + index: 6, + value: 222, + auxExistence: true, + auxIndex: 2, + auxValue: 222, + }, + }, + { + description: + "add 2 leaves (depth = 2) and generate proof on non-existing leaf WITHOUT aux node", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + ], + paramsToGetProof: 1, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: false, + siblings: [ + "96535818096110143691607859947815292580929567133286005889885442808119755306104", + ].concat(Array(63).fill(0)) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2), update the 2nd leaf and generate proof of non-existing leaf WITH aux node (which existed before update)", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: { + index: 6, + historicalRoot: + "6271825503835002167390262846571952849048843004006797408985626104559410349007", + }, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: false, + siblings: [ + "0", + "22958977272721485097221938248834413051866334275107448764221195104671274302803", + ].concat(Array(62).fill(0)) as FixedArray, + index: 6, + value: 222, + auxExistence: true, + auxIndex: 2, + auxValue: 222, + }, + }, + { + description: + "add 2 leaves (depth = 2), update the 2nd leaf and generate proof of non-existing leaf WITHOUT aux node", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 2, v: 223 }, + ], + paramsToGetProof: { + index: 1, + historicalRoot: + "6271825503835002167390262846571952849048843004006797408985626104559410349007", + }, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: false, + siblings: [ + "96535818096110143691607859947815292580929567133286005889885442808119755306104", + ].concat(Array(63).fill(0)) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: + "add 2 leaves (depth = 2), add 3rd leaf and generate proof of non-existence for the 3rd leaf in the previous root state", + leavesToInsert: [ + { i: 4, v: 444 }, + { i: 2, v: 222 }, + { i: 1, v: 111 }, + ], + paramsToGetProof: { + index: 1, + historicalRoot: + "6271825503835002167390262846571952849048843004006797408985626104559410349007", + }, + expectedProof: { + root: "6271825503835002167390262846571952849048843004006797408985626104559410349007", + existence: false, + siblings: [ + "96535818096110143691607859947815292580929567133286005889885442808119755306104", + ].concat(Array(63).fill(0)) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + ]; + + for (const testCase of testCasesNonExistence) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("keys 3 (011), 7 (111)", () => { + const testCasesNonExistence: TestCaseMTPProof[] = [ + { + description: "add 1 leaf and generate a proof on non-existing leaf", + leavesToInsert: [{ i: 3, v: 333 }], + paramsToGetProof: 7, + expectedProof: { + root: "33418405206138732565596445817172696059570130655374283008161682599505407512429", + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: "7", + value: "333", + auxExistence: true, + auxIndex: "3", + auxValue: "333", + }, + }, + { + description: + "add 2 leaves (depth = 2) and generate proof on non-existing leaf WITH aux node", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + ], + paramsToGetProof: 11, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: false, + siblings: [ + "0", + "0", + "50296473614243876656937981110997905853887938112796700896791687746944667051313", + ].concat(Array(61).fill(0)) as FixedArray, + index: "11", + value: "333", + auxExistence: true, + auxIndex: "3", + auxValue: "333", + }, + }, + { + description: + "add 2 leaves (depth = 2) and generate proof on non-existing leaf WITHOUT aux node", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + ], + paramsToGetProof: 1, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: false, + siblings: [ + "0", + "112876657748891444100900801150886368101744673616075342940779383085926542312690", + ].concat(Array(62).fill(0)) as FixedArray, + index: "1", + value: "0", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2), update the 2nd leaf and generate proof of non-existing leaf WITH aux node (which existed before update)", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: { + index: 11, + historicalRoot: + "48360753217216801628383385897610760751395521399060591925309269460841854478880", + }, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: false, + siblings: [ + "0", + "0", + "50296473614243876656937981110997905853887938112796700896791687746944667051313", + ].concat(Array(61).fill(0)) as FixedArray, + index: "11", + value: "333", + auxExistence: true, + auxIndex: "3", + auxValue: "333", + }, + }, + { + description: + "add 2 leaves (depth = 2), update the 2nd leaf and generate proof of non-existing leaf WITHOUT aux node", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 7, v: 778 }, + ], + paramsToGetProof: { + index: 1, + historicalRoot: + "48360753217216801628383385897610760751395521399060591925309269460841854478880", + }, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: false, + siblings: [ + "0", + "112876657748891444100900801150886368101744673616075342940779383085926542312690", + ].concat(Array(62).fill(0)) as FixedArray, + index: "1", + value: "0", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "add 2 leaves (depth = 2), add 3rd leaf and generate proof of non-existence for the 3rd leaf in the previous root state", + leavesToInsert: [ + { i: 3, v: 333 }, + { i: 7, v: 777 }, + { i: 11, v: 1111 }, + ], + paramsToGetProof: { + index: 11, + historicalRoot: + "48360753217216801628383385897610760751395521399060591925309269460841854478880", + }, + expectedProof: { + root: "48360753217216801628383385897610760751395521399060591925309269460841854478880", + existence: false, + siblings: [ + "0", + "0", + "50296473614243876656937981110997905853887938112796700896791687746944667051313", + ].concat(Array(61).fill(0)) as FixedArray, + index: "11", + value: "333", + auxExistence: true, + auxIndex: "3", + auxValue: "333", + }, + }, + ]; + + for (const testCase of testCasesNonExistence) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("big keys and values", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "add 10 leaves and generate a proof on non-existing WITH aux node", + leavesToInsert: [ + { + i: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + v: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + }, + { + i: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + v: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + }, + { + i: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + v: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + }, + { + i: "889985217497699235766882779777015930299841231159370680230752238312340113600", + v: "889985217497699235766882779777015930299841231159370680230752238312340113600", + }, + { + i: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + v: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + }, + { + i: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + v: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + }, + { + i: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + v: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + }, + { + i: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + v: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + }, + { + i: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + v: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + }, + { + i: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + v: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + }, + ], + paramsToGetProof: + "2254139687286372760549210172096572575821880629072851135313477335313002867071", + expectedProof: { + root: "60007161943983486146906500160381123178622458462493617850821425381979612616956", + existence: false, + siblings: [ + "15649299891651963645168066741171440452486996543233903096221914286509395708217", + "35485910319040178947164101851755181176671699873501710834388743638308164334229", + ].concat(Array(62).fill(0)) as FixedArray, + index: "2254139687286372760549210172096572575821880629072851135313477335313002867071", + value: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + auxExistence: true, + auxIndex: + "6710060555229139303017247577694107284750887011584715720178646167607892089915", + auxValue: + "6710060555229139303017247577694107284750887011584715720178646167607892089915", + }, + }, + { + description: "add 10 leaves and generate a proof on non-existing WITHOUT aux node", + leavesToInsert: [ + { + i: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + v: "17986234253083975636920416129693886882270902765181654761797265357667135152117", + }, + { + i: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + v: "18123691505823985756684232913053395870713635907333284540988946526936415011906", + }, + { + i: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + v: "18574761138418725443990802836499920062140432673318152864603722896749742947566", + }, + { + i: "889985217497699235766882779777015930299841231159370680230752238312340113600", + v: "889985217497699235766882779777015930299841231159370680230752238312340113600", + }, + { + i: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + v: "6710060555229139303017247577694107284750887011584715720178646167607892089915", + }, + { + i: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + v: "12497952624796233344034183566409825898225866478213356400863532789405613344341", + }, + { + i: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + v: "3936805208905305247536886538882195169540221794023203457168302765039729764024", + }, + { + i: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + v: "10731848384335329467520994720879479347585446432461329563566584581365237056572", + }, + { + i: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + v: "16500146780965105196157518035139529539214406883902880947728555071906521106240", + }, + { + i: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + v: "2254139687286372760549210172096572575821880629072851135313477335313002867070", + }, + ], + paramsToGetProof: + "6271287741236698691604141726361751264311688318470481595940384433868807274649", + expectedProof: { + root: "60007161943983486146906500160381123178622458462493617850821425381979612616956", + existence: false, + siblings: [ + "15649299891651963645168066741171440452486996543233903096221914286509395708217", + "5582158759613617994025042938199822589967969783458491971055101796671660471167", + "73073270877252609309304544688345883755735059749695338671799354601148846061501", + ].concat(Array(61).fill(0)) as FixedArray, + index: "6271287741236698691604141726361751264311688318470481595940384433868807274649", + value: "0", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("empty tree", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "generate proof for some key", + leavesToInsert: [], + paramsToGetProof: 1, + expectedProof: { + root: 0, + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: "generate proof for some key and zero historical root", + leavesToInsert: [{ i: 1, v: 10 }], + paramsToGetProof: { index: 1, historicalRoot: 0 }, + expectedProof: { + root: 0, + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + }); + + describe("SMT add leaf edge cases", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "Positive: add two leaves with maximum depth (less significant bits SET)", + leavesToInsert: [ + { i: genMaxBinaryNumber(63), v: 100 }, //111111111111111111111111111111111111111111111111111111111111111 + { i: genMaxBinaryNumber(64), v: 100 }, //1111111111111111111111111111111111111111111111111111111111111111 + ], + paramsToGetProof: genMaxBinaryNumber(64), + expectedProof: { + root: "110199947410708031149228851387837770054145252372569190168540009983771486866316", + existence: true, + siblings: Array(63) + .fill("0") + .concat([ + "74399159356430181752973204803851211752558544080760906099963521203069195578461", + ]) as FixedArray, + index: "18446744073709551615", + value: "100", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: "Positive: add two leaves with maximum depth (less significant bits NOT SET)", + leavesToInsert: [ + { i: 0, v: 100 }, + { i: genMaxBinaryNumber(63) + BigInt(1), v: 100 }, // 1000000000000000000000000000000000000000000000000000000000000000 + ], + paramsToGetProof: genMaxBinaryNumber(63) + BigInt(1), + expectedProof: { + root: "16625293229838138370855084455911863446233219628941478502997473061463286175203", + existence: true, + siblings: Array(63) + .fill("0") + .concat([ + "85255324799129495636878324767942437404808863678639087371922338002905282669100", + ]) as FixedArray, + index: "9223372036854775808", + value: "100", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: + "Positive: add two leaves with maximum depth (less significant bits are both SET and NOT SET)", + leavesToInsert: [ + { i: "17713686966169915918", v: 100 }, //1111010111010011101010000111000111010001000001100101001000001110 + { i: "8490314929315140110", v: 100 }, //0111010111010011101010000111000111010001000001100101001000001110 + ], + paramsToGetProof: "8490314929315140110", + expectedProof: { + root: "16484897135457263633438825596660941524517623843033410328799978262525614569225", + existence: true, + siblings: Array(63) + .fill("0") + .concat([ + "9906144696231549323869068974423946066277130279313871204886462229234859073912", + ]) as FixedArray, + index: "8490314929315140110", + value: "100", + auxExistence: false, + auxIndex: "0", + auxValue: "0", + }, + }, + { + description: "Negative: add two leaves with maximum depth + 1 (less significant bits SET)", + leavesToInsert: [ + { i: genMaxBinaryNumber(64), v: 100 }, //1111111111111111111111111111111111111111111111111111111111111111 + { i: genMaxBinaryNumber(65), v: 100, error: "Max depth reached" }, //11111111111111111111111111111111111111111111111111111111111111111 + ], + }, + { + description: + "Negative: add two leaves with maximum depth + 1 (less significant bits NOT SET)", + leavesToInsert: [ + { i: 0, v: 100 }, + { i: genMaxBinaryNumber(64) + BigInt(1), v: 100, error: "Max depth reached" }, // 10000000000000000000000000000000000000000000000000000000000000000 + ], + }, + { + description: + "Negative: add two leaves with maximum depth + 1 (less significant bits are both SET and NOT SET", + leavesToInsert: [ + { i: "17713686966169915918", v: 100 }, //1111010111010011101010000111000111010001000001100101001000001110 + { i: "36160431039879467534", v: 100, error: "Max depth reached" }, //11111010111010011101010000111000111010001000001100101001000001110 + ], + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); +}); + +describe("Root history requests", function () { + this.timeout(5000); + + let smt, historyLength; + let pubStates: { [key: string]: string | number }[] = []; + + before(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + + pubStates = []; + pubStates.push(await addLeaf(ethers, smt, 1, 10)); + pubStates.push(await addLeaf(ethers, smt, 2, 20)); + + historyLength = await smt.getRootHistoryLength(); + }); + + it("should return the root history", async () => { + // 1 root added at Smt init + 2 roots added by addLeaf + expect(historyLength).to.be.equal(3); + + const rootInfos = await smt.getRootHistory(0, historyLength); + expect(rootInfos.length).to.be.equal(historyLength); + + // check the first root, which was added at Smt init + expect(rootInfos[0].root).to.be.equal(0); + expect(rootInfos[0].replacedByRoot).to.be.equal(pubStates[0].root); + expect(rootInfos[0].createdAtTimestamp).to.be.equal(0); + expect(rootInfos[0].replacedAtTimestamp).to.be.equal(pubStates[0].timestamp); + expect(rootInfos[0].createdAtBlock).to.be.equal(0); + expect(rootInfos[0].replacedAtBlock).to.be.equal(pubStates[0].blockNumber); + + const [rootInfo] = await smt.getRootHistory(1, 1); + expect(rootInfo.root).not.to.be.equal(0); + expect(rootInfo.replacedByRoot).not.to.be.equal(0); + expect(rootInfo.createdAtTimestamp).to.be.equal(pubStates[0].timestamp); + expect(rootInfo.replacedAtTimestamp).to.be.equal(pubStates[1].timestamp); + expect(rootInfo.createdAtBlock).to.be.equal(pubStates[0].blockNumber); + expect(rootInfo.replacedAtBlock).to.be.equal(pubStates[1].blockNumber); + + const [rootInfo2] = await smt.getRootHistory(2, 1); + expect(rootInfo2.root).not.to.be.equal(0); + expect(rootInfo2.replacedByRoot).to.be.equal(0); + expect(rootInfo2.createdAtTimestamp).to.be.equal(pubStates[1].timestamp); + expect(rootInfo2.replacedAtTimestamp).to.be.equal(0); + expect(rootInfo2.createdAtBlock).to.be.equal(pubStates[1].blockNumber); + expect(rootInfo2.replacedAtBlock).to.be.equal(0); + }); + + it("should revert if length is zero", async () => { + await expect(smt.getRootHistory(0, 0)).to.be.rejectedWith("Length should be greater than 0"); + }); + + it("should revert if length limit exceeded", async () => { + await expect(smt.getRootHistory(0, 10 ** 6)).to.be.rejectedWith("Length limit exceeded"); + }); + + it("should revert if out of bounds", async () => { + await expect(smt.getRootHistory(historyLength, 100)).to.be.rejectedWith( + "Start index out of bounds", + ); + }); + + it("should NOT revert if startIndex + length >= historyLength", async () => { + let history = await smt.getRootHistory(historyLength - 1n, 100); + expect(history.length).to.be.equal(1); + history = await smt.getRootHistory(historyLength - 2n, 100); + expect(history.length).to.be.equal(2); + }); +}); + +describe("Root history duplicates", function () { + let smt; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + it("comprehensive check", async () => { + const leavesToAdd = [ + { i: 1, v: 1 }, // doubleRoot + { i: 1, v: 2 }, // singleRoot + { i: 1, v: 1 }, // doubleRoot + { i: 2, v: 1 }, // tripleRoot + { i: 2, v: 2 }, + { i: 2, v: 1 }, // tripleRoot + { i: 2, v: 2 }, + { i: 2, v: 1 }, // tripleRoot + ]; + + const addResult: { [key: string]: any }[] = []; + + for (const leaf of leavesToAdd) { + addResult.push(await addLeaf(ethers, smt, leaf.i, leaf.v)); + } + + const singleRoot = addResult[1].root; + const doubleRoot = addResult[2].root; + const tripleRoot = addResult[7].root; + const nonExistingRoot = 1; + + expect(await smt.getRootInfoListLengthByRoot(singleRoot)).to.be.equal(1); + expect(await smt.getRootInfoListLengthByRoot(doubleRoot)).to.be.equal(2); + expect(await smt.getRootInfoListLengthByRoot(tripleRoot)).to.be.equal(3); + expect(await smt.getRootInfoListLengthByRoot(nonExistingRoot)).to.be.equal(0); + + const riSingleRoot = await smt.getRootInfoListByRoot(singleRoot, 0, 100); + const riDoubleRoot = await smt.getRootInfoListByRoot(doubleRoot, 0, 100); + const riTripleRoot = await smt.getRootInfoListByRoot(tripleRoot, 0, 100); + await expect(smt.getRootInfoListByRoot(nonExistingRoot, 0, 100)).to.be.rejectedWith( + "Root does not exist", + ); + + expect(riSingleRoot.length).to.be.equal(1); + expect(riDoubleRoot.length).to.be.equal(2); + expect(riTripleRoot.length).to.be.equal(3); + + const checkRootInfo = (ri: any, riExp: any, riExpNext: any) => { + expect(ri.root).to.be.equal(riExp.rootInfo.root); + expect(ri.replacedByRoot).to.be.equal(riExpNext.rootInfo.root ?? 0); + expect(ri.createdAtBlock).to.be.equal(riExp.blockNumber); + expect(ri.replacedAtBlock).to.be.equal(riExpNext.rootInfo.createdAtBlock ?? 0); + expect(ri.createdAtTimestamp).to.be.equal(riExp.timestamp); + expect(ri.replacedAtTimestamp).to.be.equal(riExpNext.rootInfo.createdAtTimestamp ?? 0); + }; + + checkRootInfo(riSingleRoot[0], addResult[1], addResult[2]); + checkRootInfo(riDoubleRoot[0], addResult[0], addResult[1]); + checkRootInfo(riDoubleRoot[1], addResult[2], addResult[3]); + checkRootInfo(riTripleRoot[0], addResult[3], addResult[4]); + checkRootInfo(riTripleRoot[1], addResult[5], addResult[6]); + checkRootInfo(riTripleRoot[2], addResult[7], { rootInfo: {} }); + + checkRootInfo(await smt.getRootInfo(singleRoot), addResult[1], addResult[2]); + checkRootInfo(await smt.getRootInfo(doubleRoot), addResult[2], addResult[3]); + checkRootInfo(await smt.getRootInfo(tripleRoot), addResult[7], { rootInfo: {} }); + }); + + it("should revert if length is zero", async () => { + await smt.add(1, 1); + const root = await smt.getRoot(); + await expect(smt.getRootInfoListByRoot(root, 0, 0)).to.be.rejectedWith( + "Length should be greater than 0", + ); + }); + + it("should revert if length limit exceeded", async () => { + await smt.add(1, 1); + const root = await smt.getRoot(); + await expect(smt.getRootInfoListByRoot(root, 0, 10 ** 6)).to.be.rejectedWith( + "Length limit exceeded", + ); + }); + + it("should revert if out of bounds", async () => { + await smt.add(1, 1); + await smt.add(1, 2); + await smt.add(1, 1); + const root = await smt.getRoot(); + await expect(smt.getRootInfoListByRoot(root, 3, 100)).to.be.rejectedWith( + "Start index out of bounds", + ); + }); + + it("should NOT revert if startIndex + length >= historyLength", async () => { + await smt.add(1, 1); + await smt.add(1, 2); + await smt.add(1, 1); + const root = await smt.getRoot(); + const rootInfoListLength = await smt.getRootInfoListLengthByRoot(root); + let list = await smt.getRootInfoListByRoot(root, rootInfoListLength - 1n, 100); + expect(list.length).to.be.equal(1); + list = await smt.getRootInfoListByRoot(root, rootInfoListLength - 2n, 100); + expect(list.length).to.be.equal(2); + }); + + it("should return correct list and length just after init", async () => { + const root = 0; + const [rootInfo] = await smt.getRootInfoListByRoot(root, 0, 1); + expect(rootInfo.root).to.be.equal(0); + expect(rootInfo.replacedByRoot).to.be.equal(0); + expect(rootInfo.createdAtTimestamp).to.be.equal(0); + expect(rootInfo.replacedAtTimestamp).to.be.equal(0); + expect(rootInfo.createdAtBlock).to.be.equal(0); + expect(rootInfo.replacedAtBlock).to.be.equal(0); + + expect(await smt.getRootInfoListLengthByRoot(root)).to.be.equal(1); + }); +}); + +describe("Binary search in SMT root history", () => { + let binarySearch; + + async function addRootEntries(rts: RootEntry[]) { + for (const rt of rts) { + await binarySearch.addRootEntry(rt.root, rt.timestamp, rt.block); + } + } + + async function checkRootByTimeAndBlock(rts: RootEntry[], tc: TestCaseRootHistory) { + await addRootEntries(rts); + + const riByTime = await binarySearch.getRootInfoByTime(tc.timestamp); + expect(riByTime.root).to.equal(tc.expectedRoot); + + const riByBlock = await binarySearch.getHistoricalRootByBlock(tc.blockNumber); + expect(riByBlock.root).to.equal(tc.expectedRoot); + } + + async function deployContractsFixtureBinarySearch() { + ({ BSWrapper: binarySearch } = await ignition.deploy(BinarySearchTestWrapperModule)); + } + beforeEach(async () => { + await networkHelpers.loadFixture(deployContractsFixtureBinarySearch); + const latestBlockNumber = await ethers.provider.getBlockNumber(); + let blocksToMine = 19 - latestBlockNumber; + + while (blocksToMine > 0) { + await provider.request({ + method: "evm_mine", + params: [], + }); + blocksToMine--; + } + }); + + describe("Empty history ", () => { + const rootEntries: RootEntry[] = []; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return zero root for some search", + timestamp: 1, + blockNumber: 10, + expectedRoot: 0, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("One root in the root history ", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 10, + root: 1000, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the first root when equal", + timestamp: 1, + blockNumber: 10, + expectedRoot: 1000, + }, + { + description: "Should return zero when search for less than the first", + timestamp: 0, + blockNumber: 9, + expectedRoot: 0, + }, + { + description: "Should return the last root when search for greater than the last", + timestamp: 2, + blockNumber: 11, + expectedRoot: 1000, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Two roots in the root history ", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 10, + root: 1000, + }, + { + timestamp: 5, + block: 15, + root: 1500, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the first root when search for equal", + timestamp: rootEntries[0].timestamp, + blockNumber: rootEntries[0].block, + expectedRoot: rootEntries[0].root, + }, + { + description: "Should return the second root when search for equal", + timestamp: rootEntries[1].timestamp, + blockNumber: rootEntries[1].block, + expectedRoot: rootEntries[1].root, + }, + { + description: "Should return zero when search for less than the first", + timestamp: 0, + blockNumber: 9, + expectedRoot: 0, + }, + { + description: "Should return the last root when search for greater than the last", + timestamp: 6, + blockNumber: 16, + expectedRoot: rootEntries[1].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Three roots in the root history ", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 10, + root: 1000, + }, + { + timestamp: 5, + block: 15, + root: 1500, + }, + { + timestamp: 7, + block: 17, + root: 1700, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the first root when equal", + timestamp: rootEntries[0].timestamp, + blockNumber: rootEntries[0].block, + expectedRoot: rootEntries[0].root, + }, + { + description: "Should return the second root when equal", + timestamp: rootEntries[1].timestamp, + blockNumber: rootEntries[1].block, + expectedRoot: rootEntries[1].root, + }, + { + description: "Should return the third root when equal", + timestamp: rootEntries[2].timestamp, + blockNumber: rootEntries[2].block, + expectedRoot: rootEntries[2].root, + }, + { + description: "Should return zero root when search for less than the first", + timestamp: 0, + blockNumber: 9, + expectedRoot: 0, + }, + { + description: "Should return the last root when search for greater than the last", + timestamp: 9, + blockNumber: 18, + expectedRoot: rootEntries[2].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Four roots in the root history ", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 10, + root: 1000, + }, + { + timestamp: 5, + block: 15, + root: 1500, + }, + { + timestamp: 7, + block: 17, + root: 1700, + }, + { + timestamp: 8, + block: 18, + root: 1800, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the first root when equal", + timestamp: rootEntries[0].timestamp, + blockNumber: rootEntries[0].block, + expectedRoot: rootEntries[0].root, + }, + { + description: "Should return the fourth root when equal", + timestamp: rootEntries[3].timestamp, + blockNumber: rootEntries[3].block, + expectedRoot: rootEntries[3].root, + }, + { + description: "Should return zero when search for less than the first", + timestamp: rootEntries[0].timestamp - 1, + blockNumber: rootEntries[0].block - 1, + expectedRoot: 0, + }, + { + description: "Should return the last root when search for greater than the last", + timestamp: rootEntries[3].timestamp + 1, + blockNumber: rootEntries[3].block + 1, + expectedRoot: rootEntries[3].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Search in between the values", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 10, + root: 1100, + }, + { + timestamp: 3, + block: 13, + root: 1300, + }, + { + timestamp: 6, + block: 16, + root: 1600, + }, + { + timestamp: 7, + block: 17, + root: 1700, + }, + { + timestamp: 9, + block: 19, + root: 1900, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the first root when search in between the first and second", + timestamp: 2, + blockNumber: 12, + expectedRoot: rootEntries[0].root, + }, + { + description: + "Should return the fourth root when search in between the fourth and the fifth", + timestamp: 8, + blockNumber: 18, + expectedRoot: rootEntries[3].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Search in array with duplicated values", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 11, + root: 1100, + }, + { + timestamp: 1, + block: 11, + root: 1101, + }, + { + timestamp: 7, + block: 17, + root: 1700, + }, + { + timestamp: 7, + block: 17, + root: 1701, + }, + { + timestamp: 7, + block: 17, + root: 1702, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: "Should return the last root among two equal values when search for the value", + timestamp: 1, + blockNumber: 11, + expectedRoot: rootEntries[1].root, + }, + { + description: + "Should return the last root among three equal values when search for the value", + timestamp: 7, + blockNumber: 17, + expectedRoot: rootEntries[4].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); + + describe("Search in array with duplicated values and in between values", () => { + const rootEntries: RootEntry[] = [ + { + timestamp: 1, + block: 11, + root: 1100, + }, + { + timestamp: 1, + block: 11, + root: 1101, + }, + { + timestamp: 1, + block: 11, + root: 1102, + }, + { + timestamp: 3, + block: 13, + root: 1300, + }, + { + timestamp: 3, + block: 13, + root: 1301, + }, + { + timestamp: 5, + block: 15, + root: 1700, + }, + { + timestamp: 5, + block: 15, + root: 1701, + }, + { + timestamp: 5, + block: 15, + root: 1702, + }, + ]; + + const testCase: TestCaseRootHistory[] = [ + { + description: + "Should search in between the third (1st, 2nd, 3rd equal) and fourth values and return the third", + timestamp: 2, + blockNumber: 12, + expectedRoot: rootEntries[2].root, + }, + { + description: + "Should search in between the fifth (4th, 5th equal) and sixth values and return the fifth", + timestamp: 4, + blockNumber: 14, + expectedRoot: rootEntries[4].root, + }, + ]; + + for (const tc of testCase) { + it(`${tc.description}`, async () => { + await checkRootByTimeAndBlock(rootEntries, tc); + }); + } + }); +}); + +describe("Binary search in SMT proofs", () => { + let smt; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + describe("Zero root proofs", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "Should return zero proof for some search", + leavesToInsert: [], + paramsToGetProof: { + index: 1, + blockNumber: 1, + }, + expectedProof: { + root: 0, + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: "Should return zero proof for some search back in time", + leavesToInsert: [{ i: 4, v: 444 }], + paramsToGetProof: { + index: 1, + blockNumber: 1, + }, + expectedProof: { + root: 0, + existence: false, + siblings: Array(64).fill(0) as FixedArray, + index: 1, + value: 0, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); + + describe("Non-zero root proofs", () => { + const testCases: TestCaseMTPProof[] = [ + { + description: "Should return zero proof for some search current time", + leavesToInsert: [{ i: 4, v: 444 }], + paramsToGetProof: { + index: 4, + timestamp: 0, + }, + expectedProof: { + root: "22958977272721485097221938248834413051866334275107448764221195104671274302803", + existence: true, + siblings: Array(64).fill(0) as FixedArray, + index: 4, + value: 444, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + { + description: "Should return zero proof for some search current block", + leavesToInsert: [{ i: 4, v: 444 }], + paramsToGetProof: { + index: 4, + blockNumber: 0, + }, + expectedProof: { + root: "22958977272721485097221938248834413051866334275107448764221195104671274302803", + existence: true, + siblings: Array(64).fill(0) as FixedArray, + index: 4, + value: 444, + auxExistence: false, + auxIndex: 0, + auxValue: 0, + }, + }, + ]; + + for (const testCase of testCases) { + it(`${testCase.description}`, async () => { + const blockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(blockNumber); + + if (!block) { + throw new Error("Failed to fetch the latest block"); + } + + if (isProofByTime(testCase.paramsToGetProof)) { + testCase.paramsToGetProof.timestamp = block.timestamp + 1; + } + + if (isProofByBlock(testCase.paramsToGetProof)) { + testCase.paramsToGetProof.blockNumber = block.number + 1; + } + await checkTestCaseMTPProof(smt, testCase); + }); + } + }); +}); + +describe("Edge cases with exceptions", () => { + let smt; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + it("getRootInfo() should throw when root does not exist", async () => { + await smt.add(1, 1); + const root = await smt.getRoot(); + await expect(smt.getRootInfo(root)).not.to.be.rejected; + await expect(smt.getRootInfo(root + 1n)).to.be.rejectedWith("Root does not exist"); + }); + + it("getProofByRoot() should throw when root does not exist", async () => { + await smt.add(1, 1); + const root = await smt.getRoot(); + await expect(smt.getProofByRoot(1, root)).not.to.be.rejected; + await expect(smt.getProofByRoot(1, root + 1n)).to.be.rejectedWith("Root does not exist"); + }); +}); + +describe("maxDepth setting tests", () => { + let smt; + + before(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + it("Max depth should be 64", async () => { + const maxDepth = await smt.getMaxDepth(); + expect(maxDepth).to.be.equal(64); + }); + + it("Should increase max depth", async () => { + await smt.setMaxDepth(65); + const maxDepth = await smt.getMaxDepth(); + expect(maxDepth).to.be.equal(65); + await smt.setMaxDepth(128); + const maxDepth2 = await smt.getMaxDepth(); + expect(maxDepth2).to.be.equal(128); + }); + + it("Should throw when decrease max depth", async () => { + await expect(smt.setMaxDepth(127)).to.be.rejectedWith("Max depth can only be increased"); + }); + + it("Should throw when max depth is set to the same value", async () => { + await expect(smt.setMaxDepth(128)).to.be.rejectedWith("Max depth can only be increased"); + }); + + it("Should throw when max depth is set to 0", async () => { + await expect(smt.setMaxDepth(0)).to.be.rejectedWith("Max depth must be greater than zero"); + }); + + it("Should throw when max depth is set to greater than hard cap", async () => { + await expect(smt.setMaxDepth(257)).to.be.rejectedWith("Max depth is greater than hard cap"); + await expect(smt.setMaxDepth(1000000000)).to.be.rejectedWith( + "Max depth is greater than hard cap", + ); + }); +}); + +async function checkTestCaseMTPProof(smt: any, testCase: TestCaseMTPProof) { + let blockNumberDifference; + let timestampDifference; + + for (const param of testCase.leavesToInsert) { + if (param.error) { + await expect(smt.add(param.i, param.v)).to.be.rejectedWith(param.error); + continue; + } + const previousBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); + + await smt.add(param.i, param.v, { + gasPrice: 50000000000, + initialBaseFeePerGas: 25000000000, + gasLimit: 10000000, + }); + + const currentBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); + + if (!previousBlock || !currentBlock) { + throw new Error("Failed to fetch block information"); + } + + timestampDifference = currentBlock.timestamp - previousBlock.timestamp; + blockNumberDifference = currentBlock.number - previousBlock.number; + } + + let proof; + + if (["number", "bigint", "string"].includes(typeof testCase.paramsToGetProof)) { + proof = await smt.getProof(testCase.paramsToGetProof); + } + + if (isProofByHistoricalRoot(testCase.paramsToGetProof)) { + proof = await smt.getProofByRoot( + testCase.paramsToGetProof.index, + testCase.paramsToGetProof.historicalRoot, + ); + } + + if (isProofByTime(testCase.paramsToGetProof)) { + // Some adjustment in hardhat to avoid future timestamp request because some more blocks are mined instead of 1 en smt.add + if (timestampDifference > 1) { + testCase.paramsToGetProof.timestamp = + testCase.paramsToGetProof.timestamp + timestampDifference - 1; + } + + proof = await smt.getProofByTime( + testCase.paramsToGetProof.index, + testCase.paramsToGetProof.timestamp, + ); + } + + if (isProofByBlock(testCase.paramsToGetProof)) { + proof = await smt.getProofByBlock( + testCase.paramsToGetProof.index, + testCase.paramsToGetProof.blockNumber, + ); + } + + if (testCase.expectedProof === undefined) { + return; + } + + checkMtpProof(proof, testCase.expectedProof as MtpProof); +} + +function checkMtpProof(proof, expectedProof: MtpProof) { + expect(proof.root).to.equal(expectedProof.root); + expect(proof.existence).to.equal(expectedProof.existence); + checkSiblings(proof.siblings, expectedProof.siblings); + expect(proof.index).to.equal(expectedProof.index); + expect(proof.value).to.equal(expectedProof.value); + expect(proof.auxExistence).to.equal(expectedProof.auxExistence); + expect(proof.auxIndex).to.equal(expectedProof.auxIndex); + expect(proof.auxValue).to.equal(expectedProof.auxValue); +} + +function checkSiblings(siblings, expectedSiblings: FixedArray) { + expect(siblings.length).to.equal(expectedSiblings.length); + for (let i = 0; i < siblings.length; i++) { + expect(siblings[i]).to.equal(expectedSiblings[i]); + } +} + +function isProofByHistoricalRoot(proof: ParamsProof): proof is ParamsProofByHistoricalRoot { + if (typeof proof !== "object") { + return false; + } + return (proof as ParamsProofByHistoricalRoot).historicalRoot !== undefined; +} + +function isProofByTime(proof: ParamsProof): proof is ParamsProofByTime { + if (typeof proof !== "object") { + return false; + } + return (proof as ParamsProofByTime).timestamp !== undefined; +} + +function isProofByBlock(proof: ParamsProof): proof is ParamsProofByBlock { + if (typeof proof !== "object") { + return false; + } + return (proof as ParamsProofByBlock).blockNumber !== undefined; +} diff --git a/test/smtLib/smtLib.test.ts b/test/smtLib/smtLib.poseidon.test.ts similarity index 90% rename from test/smtLib/smtLib.test.ts rename to test/smtLib/smtLib.poseidon.test.ts index d0b68d1f4..d5c76174c 100644 --- a/test/smtLib/smtLib.test.ts +++ b/test/smtLib/smtLib.poseidon.test.ts @@ -1,5 +1,5 @@ import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import { addLeaf, type FixedArray, genMaxBinaryNumber, type MtpProof } from "../utils/state-utils"; import { BinarySearchTestWrapperModule, @@ -7,7 +7,7 @@ import { } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import { SMT_MAX_DEPTH } from "../../helpers/constants"; -const { ethers, networkHelpers, ignition, provider } = await network.connect(); +const { ethers, networkHelpers, ignition, provider } = await hre.network.create(); type ParamsProofByHistoricalRoot = { index: number | bigint | string; @@ -57,7 +57,7 @@ async function deployContractsFixture() { return { smtLibTestWrapper }; } -describe("Merkle tree proofs of SMT", () => { +describe("Merkle tree proofs of SMT (Poseidon hasher)", () => { let smt: any; beforeEach(async () => { @@ -1235,7 +1235,7 @@ describe("Binary search in SMT root history", () => { beforeEach(async () => { await networkHelpers.loadFixture(deployContractsFixtureBinarySearch); const latestBlockNumber = await ethers.provider.getBlockNumber(); - let blocksToMine = 15 - latestBlockNumber; + let blocksToMine = 19 - latestBlockNumber; while (blocksToMine > 0) { await provider.request({ @@ -1926,3 +1926,183 @@ function isProofByBlock(proof: ParamsProof): proof is ParamsProofByBlock { } return (proof as ParamsProofByBlock).blockNumber !== undefined; } + +describe("updateLeaf", () => { + let smt: any; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + it("updates leaf value and proof reflects new value", async () => { + await smt.add(4, 444); + const rootBefore = await smt.getRoot(); + await smt.update(4, 444, 555); + const rootAfter = await smt.getRoot(); + expect(rootAfter).not.to.equal(rootBefore); + const proof = await smt.getProof(4); + expect(proof.existence).to.be.true; + expect(proof.value).to.equal(555n); + }); + + it("old root is still accessible via getProofByRoot after update", async () => { + await smt.add(4, 444); + const rootBefore = await smt.getRoot(); + await smt.update(4, 444, 555); + const proof = await smt.getProofByRoot(4, rootBefore); + expect(proof.existence).to.be.true; + expect(proof.value).to.equal(444n); + }); + + it("root history length increments after update", async () => { + await smt.add(4, 444); + const lenBefore = await smt.getRootHistoryLength(); + await smt.update(4, 444, 555); + const lenAfter = await smt.getRootHistoryLength(); + expect(lenAfter).to.equal(lenBefore + 1n); + }); + + it("canonical root: update A to B then back to A restores original root", async () => { + await smt.add(4, 444); + await smt.add(2, 222); + const rootOriginal = await smt.getRoot(); + await smt.update(4, 444, 555); + await smt.update(4, 555, 444); + expect(await smt.getRoot()).to.equal(rootOriginal); + }); + + it("reverts with wrong old value", async () => { + await smt.add(4, 444); + await expect(smt.update(4, 999, 555)).to.be.rejectedWith("Old value mismatch"); + }); + + it("reverts when leaf index does not match path position", async () => { + await smt.add(4, 444); + await expect(smt.update(2, 444, 555)).to.be.rejectedWith("Leaf index mismatch"); + }); + + it("reverts when new value is zero", async () => { + await smt.add(4, 444); + await expect(smt.update(4, 444, 0)).to.be.rejectedWith("New leaf value should not be zero"); + }); + + it("reverts when leaf does not exist (empty tree)", async () => { + await expect(smt.update(99, 444, 555)).to.be.rejectedWith("Leaf does not exist"); + }); +}); + +describe("removeLeaf", () => { + let smt: any; + + beforeEach(async () => { + ({ smtLibTestWrapper: smt } = await networkHelpers.loadFixture(deployContractsFixture)); + }); + + it("removing the only leaf results in empty tree", async () => { + await smt.add(4, 444); + await smt.remove(4, 444); + expect(await smt.getRoot()).to.equal(0n); + const proof = await smt.getProof(4); + expect(proof.existence).to.be.false; + }); + + it("removing one of two leaves restores the single-leaf root", async () => { + await smt.add(4, 444); + const rootA = await smt.getRoot(); + await smt.add(2, 222); + await smt.remove(2, 222); + expect(await smt.getRoot()).to.equal(rootA); + const proof2 = await smt.getProof(2); + expect(proof2.existence).to.be.false; + const proof4 = await smt.getProof(4); + expect(proof4.existence).to.be.true; + expect(proof4.value).to.equal(444n); + }); + + it("remove and re-add restores original root (canonical form)", async () => { + await smt.add(4, 444); + await smt.add(2, 222); + const rootOriginal = await smt.getRoot(); + await smt.remove(2, 222); + await smt.add(2, 222); + expect(await smt.getRoot()).to.equal(rootOriginal); + }); + + it("root history length increments after remove", async () => { + await smt.add(4, 444); + const lenBefore = await smt.getRootHistoryLength(); + await smt.remove(4, 444); + const lenAfter = await smt.getRootHistoryLength(); + expect(lenAfter).to.equal(lenBefore + 1n); + }); + + it("old root is still accessible via getProofByRoot after remove", async () => { + await smt.add(4, 444); + const rootWithLeaf = await smt.getRoot(); + await smt.remove(4, 444); + const proof = await smt.getProofByRoot(4, rootWithLeaf); + expect(proof.existence).to.be.true; + expect(proof.value).to.equal(444n); + }); + + it("deep-path compression: removing one of two deep-sharing leaves restores single-leaf root", async () => { + // indices 3 (011) and 7 (111) share bits 0 and 1, pushed to depth 2 + await smt.add(3, 333); + const rootA = await smt.getRoot(); + await smt.add(7, 777); + await smt.remove(7, 777); + expect(await smt.getRoot()).to.equal(rootA); + const proof7 = await smt.getProof(7); + expect(proof7.existence).to.be.false; + const proof3 = await smt.getProof(3); + expect(proof3.existence).to.be.true; + expect(proof3.value).to.equal(333n); + }); + + it("update then remove: root matches tree where that leaf was never inserted", async () => { + await smt.add(4, 444); + const rootA = await smt.getRoot(); + await smt.add(2, 222); + await smt.update(2, 222, 223); + await smt.remove(2, 223); + expect(await smt.getRoot()).to.equal(rootA); + }); + + it("reverts with wrong old value", async () => { + await smt.add(4, 444); + await expect(smt.remove(4, 999)).to.be.rejectedWith("Old value mismatch"); + }); + + it("reverts when index does not match leaf at path position", async () => { + await smt.add(4, 444); + // index 2 (010) shares bit 0 with index 4 (100) — both are 0 at bit 0 — so traversal + // reaches the leaf for index 4 and finds node.index (4) != index (2) + await expect(smt.remove(2, 444)).to.be.rejectedWith("Leaf index mismatch"); + }); + + it("removing one leaf from a three-leaf tree produces correct two-leaf root", async () => { + await smt.add(4, 444); + await smt.add(2, 222); + const rootAB = await smt.getRoot(); // two-leaf root + await smt.add(1, 111); + await smt.remove(1, 111); + // after removing leaf(1), tree should be identical to the two-leaf tree + expect(await smt.getRoot()).to.equal(rootAB); + const proof1 = await smt.getProof(1); + expect(proof1.existence).to.be.false; + const proof4 = await smt.getProof(4); + expect(proof4.existence).to.be.true; + const proof2 = await smt.getProof(2); + expect(proof2.existence).to.be.true; + }); + + it("reverts when leaf does not exist (empty tree)", async () => { + await expect(smt.remove(99, 444)).to.be.rejectedWith("Leaf does not exist"); + }); + + it("reverts when removing an already-removed leaf", async () => { + await smt.add(4, 444); + await smt.remove(4, 444); + await expect(smt.remove(4, 444)).to.be.rejectedWith("Leaf does not exist"); + }); +}); diff --git a/test/state/state.test.ts b/test/state/state.test.ts index 4ed959226..01a0986b1 100644 --- a/test/state/state.test.ts +++ b/test/state/state.test.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; import { publishState, publishStateWithStubProof } from "../utils/state-utils"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { chainIdInfoMap } from "../../helpers/constants"; import StateModule from "../../ignition/modules/deployEverythingBasicStrategy/state"; @@ -8,7 +8,7 @@ import userStateGenesisTransitionJson from "./data/user_state_genesis_transition import userStateNextTransitionJson from "./data/user_state_next_transition.json"; import { Groth16VerifierStubModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const stateTransitionsWithProofs: any = [ userStateGenesisTransitionJson, diff --git a/test/stateLib/stateLib.test.ts b/test/stateLib/stateLib.test.ts index b8cc504eb..a38081632 100644 --- a/test/stateLib/stateLib.test.ts +++ b/test/stateLib/stateLib.test.ts @@ -1,9 +1,9 @@ import { expect } from "chai"; import { addStateToStateLib } from "../utils/state-utils"; -import { network } from "hardhat"; +import hre from "hardhat"; import { StateLibTestWrapperModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const id1Inputs = [ { id: 1, state: 10 }, diff --git a/test/utils/id-calculation-utils.ts b/test/utils/id-calculation-utils.ts index 2dc1c932e..43516c345 100644 --- a/test/utils/id-calculation-utils.ts +++ b/test/utils/id-calculation-utils.ts @@ -1,6 +1,6 @@ -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); export function calculateGroupID(requestIds: bigint[]): bigint { const types = Array(requestIds.length).fill("uint256"); diff --git a/test/utils/packData.ts b/test/utils/packData.ts index cf3b1a190..d7ea90812 100644 --- a/test/utils/packData.ts +++ b/test/utils/packData.ts @@ -1,7 +1,7 @@ import { Signer } from "ethers"; -import { network } from "hardhat"; +import hre from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await hre.network.create(); const abiCoder = new ethers.AbiCoder(); diff --git a/test/validators/authv2/index.ts b/test/validators/authv2/index.ts index 10964dce7..b729b5639 100644 --- a/test/validators/authv2/index.ts +++ b/test/validators/authv2/index.ts @@ -2,12 +2,12 @@ import { expect } from "chai"; import { prepareInputs, publishState } from "../../utils/state-utils"; import { packZKProof } from "../../utils/packData"; import { chainIdInfoMap, contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../../helpers/helperUtils"; import { AuthV2ValidatorWithGroth16VerifierStubModule } from "../../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import issuerFromGenesisStateToFirstTransitionV3 from "../common-data/issuer_from_genesis_state_to_first_transition_v3.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const testCases: any[] = [ { diff --git a/test/validators/authv3-8-32/index.ts b/test/validators/authv3-8-32/index.ts index e9cc61fed..941926f88 100644 --- a/test/validators/authv3-8-32/index.ts +++ b/test/validators/authv3-8-32/index.ts @@ -2,12 +2,12 @@ import { expect } from "chai"; import { prepareInputs, publishState } from "../../utils/state-utils"; import { packZKProof } from "../../utils/packData"; import { chainIdInfoMap, contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../../helpers/helperUtils"; import { AuthV3_8_32ValidatorWithGroth16VerifierStubModule } from "../../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import issuerFromGenesisStateToFirstTransitionV3 from "../common-data/issuer_from_genesis_state_to_first_transition_v3.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const testCases: any[] = [ { diff --git a/test/validators/authv3/index.ts b/test/validators/authv3/index.ts index 5afd568f8..8898de0da 100644 --- a/test/validators/authv3/index.ts +++ b/test/validators/authv3/index.ts @@ -2,12 +2,12 @@ import { expect } from "chai"; import { prepareInputs, publishState } from "../../utils/state-utils"; import { packZKProof } from "../../utils/packData"; import { chainIdInfoMap, contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../../helpers/helperUtils"; import { AuthV3ValidatorWithGroth16VerifierStubModule } from "../../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import issuerFromGenesisStateToFirstTransitionV3 from "../common-data/issuer_from_genesis_state_to_first_transition_v3.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const testCases: any[] = [ { diff --git a/test/validators/eth-identity/index.ts b/test/validators/eth-identity/index.ts index 50ca88956..395859d69 100644 --- a/test/validators/eth-identity/index.ts +++ b/test/validators/eth-identity/index.ts @@ -1,8 +1,8 @@ import { expect } from "chai"; -import { network } from "hardhat"; +import hre from "hardhat"; import EthIdentityValidatorModule from "../../../ignition/modules/deployEverythingBasicStrategy/ethIdentityValidator"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("Eth Identity Validator", function () { let validator: any; diff --git a/test/validators/linked-multi-query/linked-multi-query-stable.test.ts b/test/validators/linked-multi-query/linked-multi-query-stable.test.ts index dce8b6d2b..f2886b5da 100644 --- a/test/validators/linked-multi-query/linked-multi-query-stable.test.ts +++ b/test/validators/linked-multi-query/linked-multi-query-stable.test.ts @@ -2,11 +2,11 @@ import { packZKProof } from "../../utils/packData"; import { packLinkedMultiQueryValidatorParams } from "../../utils/validator-pack-utils"; import { expect } from "chai"; import { contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { LinkedMultiQueryStableValidatorWithGroth16VerifierStubModule } from "../../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import { CircuitId } from "@0xpolygonid/js-sdk"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const linkedMultiQueries = [ { circuitId: CircuitId.LinkedMultiQueryStable, queriesCount: 10 }, diff --git a/test/validators/linked-multi-query/linked-multi-query10.test.ts b/test/validators/linked-multi-query/linked-multi-query10.test.ts index 1b784f91d..65b191208 100644 --- a/test/validators/linked-multi-query/linked-multi-query10.test.ts +++ b/test/validators/linked-multi-query/linked-multi-query10.test.ts @@ -2,10 +2,10 @@ import { packZKProof } from "../../utils/packData"; import { packLinkedMultiQueryValidatorParams } from "../../utils/validator-pack-utils"; import { expect } from "chai"; import { contractsInfo } from "../../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { LinkedMultiQueryValidatorWithGroth16VerifierStubModule } from "../../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("Test linkedMultiQuery10.circom", function () { let validator, groth16Verifier; diff --git a/test/validators/mtp/index.ts b/test/validators/mtp/index.ts index 0d7673271..2c40e7b60 100644 --- a/test/validators/mtp/index.ts +++ b/test/validators/mtp/index.ts @@ -4,7 +4,7 @@ import { packValidatorParams } from "../../utils/validator-pack-utils"; import { CircuitId } from "@0xpolygonid/js-sdk"; import { chainIdInfoMap, contractsInfo, TEN_YEARS } from "../../../helpers/constants"; import { packZKProof } from "../../utils/packData"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryMTPV2ValidatorModule from "../../../ignition/modules/deployEverythingBasicStrategy/credentialAtomicQueryMTPV2Validator"; import { getChainId } from "../../../helpers/helperUtils"; import issuerGenesisState from "../common-data/issuer_genesis_state.json"; @@ -15,7 +15,7 @@ import validMtpUserNonGenesis from "./data/valid_mtp_user_non_genesis.json"; import issuerNextStateTransition from "../common-data/issuer_next_state_transition.json"; import userNextStateTransition from "../common-data/user_next_state_transition.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const tenYears = TEN_YEARS; const testCases: any[] = [ diff --git a/test/validators/sig/index.ts b/test/validators/sig/index.ts index 20b3c03b2..ed7fd5eaa 100644 --- a/test/validators/sig/index.ts +++ b/test/validators/sig/index.ts @@ -4,7 +4,7 @@ import { packValidatorParams } from "../../utils/validator-pack-utils"; import { CircuitId } from "@0xpolygonid/js-sdk"; import { chainIdInfoMap, contractsInfo, TEN_YEARS } from "../../../helpers/constants"; import { packZKProof } from "../../utils/packData"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQuerySigV2ValidatorModule from "../../../ignition/modules/deployEverythingBasicStrategy/credentialAtomicQuerySigV2Validator"; import { getChainId } from "../../../helpers/helperUtils"; import issuerGenesisState from "../common-data/issuer_genesis_state.json"; @@ -15,7 +15,7 @@ import validSigUserNonGenesis from "./data/valid_sig_user_non_genesis.json"; import issuerNextStateTransition from "../common-data/issuer_next_state_transition.json"; import userNextStateTransition from "../common-data/user_next_state_transition.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const tenYears = TEN_YEARS; const testCases: any[] = [ diff --git a/test/validators/v3-stable/index.ts b/test/validators/v3-stable/index.ts index 32a3b6aaf..77aac0fb7 100644 --- a/test/validators/v3-stable/index.ts +++ b/test/validators/v3-stable/index.ts @@ -5,7 +5,7 @@ import { calculateQueryHashV3 } from "../../utils/query-hash-utils"; import { CircuitId } from "@0xpolygonid/js-sdk"; import { chainIdInfoMap, contractsInfo, TEN_YEARS } from "../../../helpers/constants"; import { packZKProof } from "../../utils/packData"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryV3StableValidatorModule from "../../../ignition/modules/deployEverythingBasicStrategy/credentialAtomicQueryV3StableValidator"; import { getChainId } from "../../../helpers/helperUtils"; import issuerFromGenesisStateToFirstTransitionV3 from "../common-data/issuer_from_genesis_state_to_first_transition_v3.json"; @@ -45,7 +45,7 @@ import validBjjUserGenesisAuthDisabledV3WrongId_16_16_64_16_32 from "./data-16-1 import validMtpUserGenesisAuthDisabledV3WrongId_16_16_64_16_32 from "./data-16-16-64-16-32/valid_mtp_user_genesis_auth_disabled_v3_wrong_id.json"; import validBjjUserFirstIssuerGenesisV3_16_16_64_16_32 from "./data-16-16-64-16-32/valid_bjj_user_first_issuer_genesis_v3.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const tenYears = TEN_YEARS; const testCases: any[] = [ diff --git a/test/validators/v3/index.ts b/test/validators/v3/index.ts index 91dbe8f8f..b6400cbe9 100644 --- a/test/validators/v3/index.ts +++ b/test/validators/v3/index.ts @@ -5,7 +5,7 @@ import { calculateQueryHashV3 } from "../../utils/query-hash-utils"; import { CircuitId } from "@0xpolygonid/js-sdk"; import { chainIdInfoMap, contractsInfo, TEN_YEARS } from "../../../helpers/constants"; import { packZKProof } from "../../utils/packData"; -import { network } from "hardhat"; +import hre from "hardhat"; import CredentialAtomicQueryV3ValidatorModule from "../../../ignition/modules/deployEverythingBasicStrategy/credentialAtomicQueryV3Validator"; import { getChainId } from "../../../helpers/helperUtils"; import issuerFromGenesisStateToFirstTransitionV3 from "../common-data/issuer_from_genesis_state_to_first_transition_v3.json"; @@ -29,7 +29,7 @@ import validBjjUserGenesisAuthDisabledV3WrongId from "./data/valid_bjj_user_gene import validMtpUserGenesisAuthDisabledV3WrongId from "./data/valid_mtp_user_genesis_auth_disabled_v3_wrong_id.json"; import validBjjUserFirstIssuerGenesisV3 from "./data/valid_bjj_user_first_issuer_genesis_v3.json"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); const tenYears = TEN_YEARS; const testCases: any[] = [ diff --git a/test/verifier/embedded-verifier.test.ts b/test/verifier/embedded-verifier.test.ts index 782d82ffc..7afffe52b 100644 --- a/test/verifier/embedded-verifier.test.ts +++ b/test/verifier/embedded-verifier.test.ts @@ -1,7 +1,7 @@ import { beforeEach } from "mocha"; import { expect } from "chai"; import { chainIdInfoMap } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { AuthValidatorStubModule, @@ -10,7 +10,7 @@ import { RequestValidatorStubModule, } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, ignition, networkHelpers } = await network.connect(); +const { ethers, ignition, networkHelpers } = await hre.network.create(); describe("EmbeddedVerifier tests", function () { let verifier, state, validator, signer: any; diff --git a/test/verifier/requestDisableable.test.ts b/test/verifier/requestDisableable.test.ts index 24c8e5b73..538283e05 100644 --- a/test/verifier/requestDisableable.test.ts +++ b/test/verifier/requestDisableable.test.ts @@ -1,7 +1,7 @@ import { beforeEach } from "mocha"; import { expect } from "chai"; import { chainIdInfoMap } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { Groth16VerifierStubModule, @@ -9,7 +9,7 @@ import { RequestValidatorStubModule, } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("RequestDisableable tests", function () { let verifier, validator: any; diff --git a/test/verifier/requestOwnership.test.ts b/test/verifier/requestOwnership.test.ts index 3ad05bd09..5a876f548 100644 --- a/test/verifier/requestOwnership.test.ts +++ b/test/verifier/requestOwnership.test.ts @@ -1,7 +1,7 @@ import { beforeEach } from "mocha"; import { expect } from "chai"; import { chainIdInfoMap } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { Groth16VerifierStubModule, @@ -9,7 +9,7 @@ import { RequestValidatorStubModule, } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); describe("RequestOwnership tests", function () { let verifier, validator: any; diff --git a/test/verifier/universal-verifier.test.ts b/test/verifier/universal-verifier.test.ts index b1db1e9a4..35f1dcb17 100644 --- a/test/verifier/universal-verifier.test.ts +++ b/test/verifier/universal-verifier.test.ts @@ -4,7 +4,7 @@ import { AbiCoder, Block } from "ethers"; import { byteEncoder, calculateMultiRequestId, CircuitId } from "@0xpolygonid/js-sdk"; import { chainIdInfoMap, contractsInfo } from "../../helpers/constants"; import { beforeEach } from "mocha"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import UniversalVerifierModule from "../../ignition/modules/deployEverythingBasicStrategy/universalVerifier"; import { @@ -12,7 +12,7 @@ import { RequestValidatorStubModule, } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("Universal Verifier tests", function () { let request, paramsFromValidator, multiRequest, authResponse, response: any; diff --git a/test/verifier/validatorWhitelist.test.ts b/test/verifier/validatorWhitelist.test.ts index dd7b93f81..293865aa9 100644 --- a/test/verifier/validatorWhitelist.test.ts +++ b/test/verifier/validatorWhitelist.test.ts @@ -1,7 +1,7 @@ import { beforeEach } from "mocha"; import { expect } from "chai"; import { chainIdInfoMap } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import { Groth16VerifierStubModule, @@ -9,7 +9,7 @@ import { ValidatorWhitelistTestWrapperModule, } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; -const { ethers, networkHelpers, ignition } = await network.connect(); +const { ethers, networkHelpers, ignition } = await hre.network.create(); describe("ValidatorWhitelist tests", function () { let verifier, validator: any; diff --git a/test/verifier/verifier.test.ts b/test/verifier/verifier.test.ts index 01d874f9c..9415c6939 100644 --- a/test/verifier/verifier.test.ts +++ b/test/verifier/verifier.test.ts @@ -1,13 +1,13 @@ import { beforeEach } from "mocha"; import { expect } from "chai"; import { chainIdInfoMap, contractsInfo } from "../../helpers/constants"; -import { network } from "hardhat"; +import hre from "hardhat"; import { getChainId } from "../../helpers/helperUtils"; import StateModule from "../../ignition/modules/deployEverythingBasicStrategy/state"; import { Groth16VerifierStubModule } from "../../ignition/modules/deployEverythingBasicStrategy/testHelpers"; import { calculateGroupId, calculateMultiRequestId, calculateRequestId } from "@0xpolygonid/js-sdk"; -const { ethers, ignition } = await network.connect(); +const { ethers, ignition } = await hre.network.create(); describe("Verifier tests", function () { let sender: any;