mirror of
https://github.com/vacp2p/rln-interep-contract.git
synced 2025-02-28 06:00:43 +00:00
feat: use hardhat-deploy, clean up poseidon hasher tests
This commit is contained in:
parent
a95e388991
commit
4cbfc0feb0
9
common/chain-utils.ts
Normal file
9
common/chain-utils.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export const devNets = [
|
||||
'hardhat',
|
||||
'localhost',
|
||||
'goerli',
|
||||
]
|
||||
|
||||
export const prodNets = ['mainnet']
|
||||
|
||||
export const isDevNet = (networkName: string) => devNets.includes(networkName)
|
3
common/index.ts
Normal file
3
common/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
// barrel for all other utils
|
||||
export * from './interep-utils';
|
||||
export * from './chain-utils';
|
33
common/interep-utils.ts
Normal file
33
common/interep-utils.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import {utils} from "ethers";
|
||||
|
||||
export const sToBytes32 = (str: string): string => {
|
||||
return utils.formatBytes32String(str);
|
||||
}
|
||||
|
||||
export const SNARK_SCALAR_FIELD = BigInt(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
||||
)
|
||||
|
||||
export const createGroupId = (provider: string, name: string): bigint => {
|
||||
const providerBytes = sToBytes32(provider);
|
||||
const nameBytes = sToBytes32(name);
|
||||
return BigInt(utils.solidityKeccak256(["bytes32", "bytes32"], [providerBytes, nameBytes])) % SNARK_SCALAR_FIELD
|
||||
}
|
||||
|
||||
const providers = ['github', 'twitter', 'reddit'];
|
||||
const tiers = ['bronze', 'silver', 'gold'];
|
||||
|
||||
export const getGroups = () => {
|
||||
return providers.flatMap(provider => tiers.map(tier => {
|
||||
return {
|
||||
provider: sToBytes32(provider),
|
||||
name: sToBytes32(tier),
|
||||
root: 1,
|
||||
depth: 10,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
export const getValidGroups = () => {
|
||||
return getGroups().filter(group => group.name !== sToBytes32('bronze'));
|
||||
}
|
@ -1,98 +1,151 @@
|
||||
pragma solidity 0.8.15;
|
||||
|
||||
import { IPoseidonHasher } from "./PoseidonHasher.sol";
|
||||
import {IPoseidonHasher} from "./PoseidonHasher.sol";
|
||||
import {IValidGroupStorage} from "./ValidGroupStorage.sol";
|
||||
import {IInterep} from "@interep/contracts/IInterep.sol";
|
||||
|
||||
contract RLN {
|
||||
uint256 public immutable MEMBERSHIP_DEPOSIT;
|
||||
uint256 public immutable DEPTH;
|
||||
uint256 public immutable SET_SIZE;
|
||||
uint256 public immutable MEMBERSHIP_DEPOSIT;
|
||||
uint256 public immutable DEPTH;
|
||||
uint256 public immutable SET_SIZE;
|
||||
|
||||
uint256 public pubkeyIndex = 0;
|
||||
mapping(uint256 => uint256) public members;
|
||||
uint256 public pubkeyIndex = 0;
|
||||
mapping(uint256 => uint256) public members;
|
||||
|
||||
IPoseidonHasher public poseidonHasher;
|
||||
IPoseidonHasher public poseidonHasher;
|
||||
IValidGroupStorage public validGroupStorage;
|
||||
IInterep public interep;
|
||||
|
||||
event MemberRegistered(uint256 pubkey, uint256 index);
|
||||
event MemberWithdrawn(uint256 pubkey, uint256 index);
|
||||
event MemberRegistered(uint256 pubkey, uint256 index);
|
||||
event MemberWithdrawn(uint256 pubkey, uint256 index);
|
||||
|
||||
constructor(
|
||||
uint256 membershipDeposit,
|
||||
uint256 depth,
|
||||
address _poseidonHasher
|
||||
) {
|
||||
MEMBERSHIP_DEPOSIT = membershipDeposit;
|
||||
DEPTH = depth;
|
||||
SET_SIZE = 1 << depth;
|
||||
poseidonHasher = IPoseidonHasher(_poseidonHasher);
|
||||
}
|
||||
constructor(
|
||||
uint256 membershipDeposit,
|
||||
uint256 depth,
|
||||
address _poseidonHasher,
|
||||
address _validGroupStorage
|
||||
) {
|
||||
MEMBERSHIP_DEPOSIT = membershipDeposit;
|
||||
DEPTH = depth;
|
||||
SET_SIZE = 1 << depth;
|
||||
poseidonHasher = IPoseidonHasher(_poseidonHasher);
|
||||
validGroupStorage = IValidGroupStorage(_validGroupStorage);
|
||||
interep = IInterep(validGroupStorage.interep());
|
||||
}
|
||||
|
||||
function register(uint256 pubkey) external payable {
|
||||
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
|
||||
require(msg.value == MEMBERSHIP_DEPOSIT, "RLN, register: membership deposit is not satisfied");
|
||||
_register(pubkey);
|
||||
}
|
||||
function register(uint256 pubkey) external payable {
|
||||
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
|
||||
require(
|
||||
msg.value == MEMBERSHIP_DEPOSIT,
|
||||
"RLN, register: membership deposit is not satisfied"
|
||||
);
|
||||
_register(pubkey);
|
||||
}
|
||||
|
||||
function registerBatch(uint256[] calldata pubkeys) external payable {
|
||||
uint256 pubkeylen = pubkeys.length;
|
||||
require(pubkeyIndex + pubkeylen <= SET_SIZE, "RLN, registerBatch: set is full");
|
||||
require(msg.value == MEMBERSHIP_DEPOSIT * pubkeylen, "RLN, registerBatch: membership deposit is not satisfied");
|
||||
for (uint256 i = 0; i < pubkeylen; i++) {
|
||||
_register(pubkeys[i]);
|
||||
}
|
||||
}
|
||||
function register(
|
||||
uint256 groupId,
|
||||
string calldata signal,
|
||||
uint256 nullifierHash,
|
||||
uint256 externalNullifier,
|
||||
uint256[8] calldata proof,
|
||||
uint256 pubkey
|
||||
) external {
|
||||
require(
|
||||
validGroupStorage.isValidGroup(groupId),
|
||||
"RLN, register: invalid interep group"
|
||||
);
|
||||
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
|
||||
// TODO: verify proof
|
||||
_register(pubkey);
|
||||
}
|
||||
|
||||
function _register(uint256 pubkey) internal {
|
||||
members[pubkeyIndex] = pubkey;
|
||||
emit MemberRegistered(pubkey, pubkeyIndex);
|
||||
pubkeyIndex += 1;
|
||||
}
|
||||
function registerBatch(uint256[] calldata pubkeys) external payable {
|
||||
uint256 pubkeylen = pubkeys.length;
|
||||
require(
|
||||
pubkeyIndex + pubkeylen <= SET_SIZE,
|
||||
"RLN, registerBatch: set is full"
|
||||
);
|
||||
require(
|
||||
msg.value == MEMBERSHIP_DEPOSIT * pubkeylen,
|
||||
"RLN, registerBatch: membership deposit is not satisfied"
|
||||
);
|
||||
for (uint256 i = 0; i < pubkeylen; i++) {
|
||||
_register(pubkeys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function withdrawBatch(
|
||||
uint256[] calldata secrets,
|
||||
uint256[] calldata pubkeyIndexes,
|
||||
address payable[] calldata receivers
|
||||
) external {
|
||||
uint256 batchSize = secrets.length;
|
||||
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
|
||||
require(batchSize == pubkeyIndexes.length, "RLN, withdrawBatch: batch size mismatch pubkey indexes");
|
||||
require(batchSize == receivers.length, "RLN, withdrawBatch: batch size mismatch receivers");
|
||||
for (uint256 i = 0; i < batchSize; i++) {
|
||||
_withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);
|
||||
}
|
||||
}
|
||||
function _register(uint256 pubkey) internal {
|
||||
members[pubkeyIndex] = pubkey;
|
||||
emit MemberRegistered(pubkey, pubkeyIndex);
|
||||
pubkeyIndex += 1;
|
||||
}
|
||||
|
||||
function withdraw(
|
||||
uint256 secret,
|
||||
uint256 _pubkeyIndex,
|
||||
address payable receiver
|
||||
) external {
|
||||
_withdraw(secret, _pubkeyIndex, receiver);
|
||||
}
|
||||
function withdrawBatch(
|
||||
uint256[] calldata secrets,
|
||||
uint256[] calldata pubkeyIndexes,
|
||||
address payable[] calldata receivers
|
||||
) external {
|
||||
uint256 batchSize = secrets.length;
|
||||
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
|
||||
require(
|
||||
batchSize == pubkeyIndexes.length,
|
||||
"RLN, withdrawBatch: batch size mismatch pubkey indexes"
|
||||
);
|
||||
require(
|
||||
batchSize == receivers.length,
|
||||
"RLN, withdrawBatch: batch size mismatch receivers"
|
||||
);
|
||||
for (uint256 i = 0; i < batchSize; i++) {
|
||||
_withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function _withdraw(
|
||||
uint256 secret,
|
||||
uint256 _pubkeyIndex,
|
||||
address payable receiver
|
||||
) internal {
|
||||
require(_pubkeyIndex < SET_SIZE, "RLN, _withdraw: invalid pubkey index");
|
||||
require(members[_pubkeyIndex] != 0, "RLN, _withdraw: member doesn't exist");
|
||||
require(receiver != address(0), "RLN, _withdraw: empty receiver address");
|
||||
function withdraw(
|
||||
uint256 secret,
|
||||
uint256 _pubkeyIndex,
|
||||
address payable receiver
|
||||
) external {
|
||||
_withdraw(secret, _pubkeyIndex, receiver);
|
||||
}
|
||||
|
||||
// derive public key
|
||||
uint256 pubkey = hash(secret);
|
||||
require(members[_pubkeyIndex] == pubkey, "RLN, _withdraw: not verified");
|
||||
function _withdraw(
|
||||
uint256 secret,
|
||||
uint256 _pubkeyIndex,
|
||||
address payable receiver
|
||||
) internal {
|
||||
require(
|
||||
_pubkeyIndex < SET_SIZE,
|
||||
"RLN, _withdraw: invalid pubkey index"
|
||||
);
|
||||
require(
|
||||
members[_pubkeyIndex] != 0,
|
||||
"RLN, _withdraw: member doesn't exist"
|
||||
);
|
||||
require(
|
||||
receiver != address(0),
|
||||
"RLN, _withdraw: empty receiver address"
|
||||
);
|
||||
|
||||
// delete member
|
||||
members[_pubkeyIndex] = 0;
|
||||
// derive public key
|
||||
uint256 pubkey = hash(secret);
|
||||
require(
|
||||
members[_pubkeyIndex] == pubkey,
|
||||
"RLN, _withdraw: not verified"
|
||||
);
|
||||
|
||||
// refund deposit
|
||||
(bool sent, bytes memory data) = receiver.call{value: MEMBERSHIP_DEPOSIT}("");
|
||||
// delete member
|
||||
members[_pubkeyIndex] = 0;
|
||||
|
||||
// refund deposit
|
||||
(bool sent, bytes memory data) = receiver.call{
|
||||
value: MEMBERSHIP_DEPOSIT
|
||||
}("");
|
||||
require(sent, "transfer failed");
|
||||
|
||||
emit MemberWithdrawn(pubkey, _pubkeyIndex);
|
||||
}
|
||||
emit MemberWithdrawn(pubkey, _pubkeyIndex);
|
||||
}
|
||||
|
||||
function hash(uint256 input) internal view returns (uint256) {
|
||||
return poseidonHasher.hash(input);
|
||||
}
|
||||
}
|
||||
function hash(uint256 input) internal view returns (uint256) {
|
||||
return poseidonHasher.hash(input);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,12 @@ pragma solidity ^0.8.4;
|
||||
|
||||
import "@interep/contracts/Interep.sol";
|
||||
|
||||
interface IValidGroupStorage {
|
||||
function isValidGroup(uint256 groupId) external view returns (bool);
|
||||
|
||||
function interep() external view returns (address);
|
||||
}
|
||||
|
||||
contract ValidGroupStorage {
|
||||
mapping(uint256 => bool) public validGroups;
|
||||
|
||||
|
16
deploy/001_deploy_poseidon_hasher.ts
Normal file
16
deploy/001_deploy_poseidon_hasher.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
import {DeployFunction} from 'hardhat-deploy/types';
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const {deployments, getUnnamedAccounts} = hre;
|
||||
const {deploy} = deployments;
|
||||
|
||||
const [deployer] = await getUnnamedAccounts();
|
||||
|
||||
await deploy('PoseidonHasher', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
});
|
||||
};
|
||||
export default func;
|
||||
func.tags = ['PoseidonHasher'];
|
35
deploy/002_deploy_interep_test.ts
Normal file
35
deploy/002_deploy_interep_test.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
import {DeployFunction} from 'hardhat-deploy/types';
|
||||
import {
|
||||
getGroups,
|
||||
isDevNet
|
||||
} from '../common';
|
||||
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const {deployments, getUnnamedAccounts} = hre;
|
||||
const {deploy} = deployments;
|
||||
|
||||
const [deployer] = await getUnnamedAccounts();
|
||||
|
||||
const interepTest = await deploy('InterepTest', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
args: [],
|
||||
});
|
||||
|
||||
const contract = await hre.ethers.getContractAt('InterepTest', interepTest.address);
|
||||
const groups = getGroups();
|
||||
const groupInsertionTx = await contract.updateGroups(groups);
|
||||
await groupInsertionTx.wait();
|
||||
|
||||
};
|
||||
export default func;
|
||||
func.tags = ['InterepTest'];
|
||||
// skip when running on mainnet
|
||||
func.skip = async (hre: HardhatRuntimeEnvironment) => {
|
||||
if (isDevNet(hre.network.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
23
deploy/003_deploy_valid_group_storage.ts
Normal file
23
deploy/003_deploy_valid_group_storage.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
import {DeployFunction} from 'hardhat-deploy/types';
|
||||
import {getValidGroups, isDevNet} from '../common';
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const {deployments, getUnnamedAccounts} = hre;
|
||||
const {deploy} = deployments;
|
||||
|
||||
const [deployer] = await getUnnamedAccounts();
|
||||
|
||||
if (!isDevNet(hre.network.name)) {
|
||||
throw new Error('Interep not deployed on mainnet yet.')
|
||||
}
|
||||
const interepAddress = isDevNet(hre.network.name) ? (await deployments.get('InterepTest')).address : '0x0000000000000000000000000000000000000000';
|
||||
|
||||
await deploy('ValidGroupStorage', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
args: [interepAddress, getValidGroups()]
|
||||
});
|
||||
};
|
||||
export default func;
|
||||
func.tags = ['ValidGroupStorage'];
|
20
deploy/004_deploy_rln.ts
Normal file
20
deploy/004_deploy_rln.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
import {DeployFunction} from 'hardhat-deploy/types';
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const {deployments, getUnnamedAccounts} = hre;
|
||||
const {deploy} = deployments;
|
||||
|
||||
const [deployer] = await getUnnamedAccounts();
|
||||
|
||||
const poseidonHasherAddress = (await deployments.get('PoseidonHasher')).address;
|
||||
const validGroupStorageAddress = (await deployments.get('ValidGroupStorage')).address;
|
||||
|
||||
await deploy('RLN', {
|
||||
from: deployer,
|
||||
log: true,
|
||||
args: [1000000000000000, 20, poseidonHasherAddress, validGroupStorageAddress]
|
||||
});
|
||||
};
|
||||
export default func;
|
||||
func.tags = ['RLN'];
|
1
deployments/localhost/.chainId
Normal file
1
deployments/localhost/.chainId
Normal file
@ -0,0 +1 @@
|
||||
31337
|
354
deployments/localhost/InterepTest.json
Normal file
354
deployments/localhost/InterepTest.json
Normal file
File diff suppressed because one or more lines are too long
73
deployments/localhost/PoseidonHasher.json
Normal file
73
deployments/localhost/PoseidonHasher.json
Normal file
File diff suppressed because one or more lines are too long
399
deployments/localhost/RLN.json
Normal file
399
deployments/localhost/RLN.json
Normal file
File diff suppressed because one or more lines are too long
200
deployments/localhost/ValidGroupStorage.json
Normal file
200
deployments/localhost/ValidGroupStorage.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,50 @@
|
||||
{
|
||||
"language": "Solidity",
|
||||
"sources": {
|
||||
"@interep/contracts/IInterep.sol": {
|
||||
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Interep interface.\n/// @dev Interface of a Interep contract.\ninterface IInterep {\n struct Verifier {\n address contractAddress;\n uint8 merkleTreeDepth;\n }\n\n struct Group {\n bytes32 provider;\n bytes32 name;\n uint256 root;\n uint8 depth;\n }\n\n /// @dev Emitted when a Semaphore proof is verified.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n event ProofVerified(uint256 indexed groupId, bytes32 signal);\n\n /// @dev Emitted when an Interep group is updated.\n /// @param groupId: Id of the group.\n /// @param provider: Provider of the group.\n /// @param name: Name of the group.\n /// @param root: Root hash of the tree.\n /// @param depth: Depth of the tree.\n event GroupUpdated(\n uint256 groupId,\n bytes32 indexed provider,\n bytes32 indexed name,\n uint256 root,\n uint8 indexed depth\n );\n\n /// @dev Updates the Interep groups.\n /// @param groups: List of Interep groups.\n function updateGroups(Group[] calldata groups) external;\n\n /// @dev Saves the nullifier hash to avoid double signaling and emits an event\n /// if the zero-knowledge proof is valid.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external;\n\n /// @dev Returns the root hash of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Root hash of the group.\n function getRoot(uint256 groupId) external view returns (uint256);\n\n /// @dev Returns the tree depth of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Tree depth of the group.\n function getDepth(uint256 groupId) external view returns (uint8);\n}\n"
|
||||
},
|
||||
"@semaphore-protocol/contracts/base/SemaphoreConstants.sol": {
|
||||
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n"
|
||||
},
|
||||
"@semaphore-protocol/contracts/base/SemaphoreCore.sol": {
|
||||
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\nimport \"../interfaces/ISemaphoreCore.sol\";\nimport \"../interfaces/IVerifier.sol\";\n\n/// @title Semaphore core contract.\n/// @notice Minimal code to allow users to signal their endorsement of an arbitrary string.\n/// @dev The following code verifies that the proof is correct and saves the hash of the\n/// nullifier to prevent double-signaling. External nullifier and Merkle trees (i.e. groups) must be\n/// managed externally.\ncontract SemaphoreCore is ISemaphoreCore {\n /// @dev Asserts that no nullifier already exists and if the zero-knowledge proof is valid.\n /// Otherwise it reverts.\n /// @param signal: Semaphore signal.\n /// @param root: Root of the Merkle tree.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n /// @param verifier: Verifier address.\n function _verifyProof(\n bytes32 signal,\n uint256 root,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n IVerifier verifier\n ) internal view {\n uint256 signalHash = _hashSignal(signal);\n\n verifier.verifyProof(\n [proof[0], proof[1]],\n [[proof[2], proof[3]], [proof[4], proof[5]]],\n [proof[6], proof[7]],\n [root, nullifierHash, signalHash, externalNullifier]\n );\n }\n\n /// @dev Creates a keccak256 hash of the signal.\n /// @param signal: Semaphore signal.\n /// @return Hash of the signal.\n function _hashSignal(bytes32 signal) private pure returns (uint256) {\n return uint256(keccak256(abi.encodePacked(signal))) >> 8;\n }\n}\n"
|
||||
},
|
||||
"@semaphore-protocol/contracts/interfaces/ISemaphoreCore.sol": {
|
||||
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\n/// @title SemaphoreCore interface.\n/// @dev Interface of SemaphoreCore contract.\ninterface ISemaphoreCore {\n /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.\n /// @param nullifierHash: Hash of external and identity nullifiers.\n event NullifierHashAdded(uint256 nullifierHash);\n}\n"
|
||||
},
|
||||
"@semaphore-protocol/contracts/interfaces/IVerifier.sol": {
|
||||
"content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.4;\n\n/// @title Verifier interface.\n/// @dev Interface of Verifier contract.\ninterface IVerifier {\n function verifyProof(\n uint256[2] memory a,\n uint256[2][2] memory b,\n uint256[2] memory c,\n uint256[4] memory input\n ) external view;\n}\n"
|
||||
},
|
||||
"contracts/InterepTest.sol": {
|
||||
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@interep/contracts/IInterep.sol\";\nimport \"@semaphore-protocol/contracts/interfaces/IVerifier.sol\";\nimport \"@semaphore-protocol/contracts/base/SemaphoreCore.sol\";\nimport \"@semaphore-protocol/contracts/base/SemaphoreConstants.sol\";\n\ncontract InterepTest is IInterep, SemaphoreCore {\n mapping(uint256 => Group) public groups;\n\n /// @dev mimics https://github.com/interep-project/contracts/blob/main/contracts/Interep.sol but ignores the verification mechanism\n constructor() {}\n\n /// @dev See {IInterep-updateGroups}.\n function updateGroups(Group[] calldata _groups) external override {\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(\n keccak256(\n abi.encodePacked(_groups[i].provider, _groups[i].name)\n )\n ) % SNARK_SCALAR_FIELD;\n\n _updateGroup(groupId, _groups[i]);\n }\n }\n\n /// @dev See {IInterep-getRoot}.\n function getRoot(uint256 groupId) public view override returns (uint256) {\n return groups[groupId].root;\n }\n\n /// @dev See {IInterep-getDepth}.\n function getDepth(uint256 groupId) public view override returns (uint8) {\n return groups[groupId].depth;\n }\n\n /// @dev Updates an Interep group.\n /// @param groupId: Id of the group.\n /// @param group: Group data.\n function _updateGroup(uint256 groupId, Group calldata group) private {\n groups[groupId] = group;\n\n emit GroupUpdated(\n groupId,\n group.provider,\n group.name,\n group.root,\n group.depth\n );\n }\n\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external override {}\n}\n"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"optimizer": {
|
||||
"enabled": false,
|
||||
"runs": 200
|
||||
},
|
||||
"outputSelection": {
|
||||
"*": {
|
||||
"*": [
|
||||
"abi",
|
||||
"evm.bytecode",
|
||||
"evm.deployedBytecode",
|
||||
"evm.methodIdentifiers",
|
||||
"metadata",
|
||||
"devdoc",
|
||||
"userdoc",
|
||||
"storageLayout",
|
||||
"evm.gasEstimates"
|
||||
],
|
||||
"": [
|
||||
"ast"
|
||||
]
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"useLiteralContent": true
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
import * as dotenv from "dotenv";
|
||||
|
||||
import { HardhatUserConfig, task } from "hardhat/config";
|
||||
import { NetworksUserConfig } from "hardhat/types";
|
||||
|
||||
import "hardhat-deploy";
|
||||
import "@nomiclabs/hardhat-ethers";
|
||||
import "@nomiclabs/hardhat-waffle";
|
||||
import "hardhat-gas-reporter";
|
||||
import "solidity-coverage";
|
||||
import { NetworksUserConfig } from "hardhat/types";
|
||||
|
||||
dotenv.config();
|
||||
const {GOERLI_URL,PRIVATE_KEY} = process.env;
|
||||
|
@ -13,15 +13,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@interep/contracts": "0.6.0",
|
||||
"@semaphore-protocol/contracts": "2.6.1",
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.6",
|
||||
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.1.0",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||
"@semaphore-protocol/contracts": "2.6.1",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"chai": "^4.3.6",
|
||||
"ethereum-waffle": "^3.4.4",
|
||||
"ethers": "^5.6.9",
|
||||
"ethers": "^5.7.2",
|
||||
"hardhat": "^2.9.9",
|
||||
"hardhat-deploy": "0.11.20",
|
||||
"hardhat-gas-reporter": "^1.0.8",
|
||||
"solidity-coverage": "^0.7.21",
|
||||
"ts-node": "^10.8.1",
|
||||
@ -30,4 +31,4 @@
|
||||
"dependencies": {
|
||||
"dotenv": "^16.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
// We require the Hardhat Runtime Environment explicitly here. This is optional
|
||||
// but useful for running the script in a standalone fashion through `node <script>`.
|
||||
//
|
||||
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
|
||||
// Runtime Environment's members available in the global scope.
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
async function main() {
|
||||
// Hardhat always runs the compile task when running scripts with its command
|
||||
// line interface.
|
||||
//
|
||||
// If this script is run directly using `node` you may want to call compile
|
||||
// manually to make sure everything is compiled
|
||||
// await hre.run('compile');
|
||||
|
||||
// We get the contract to deploy
|
||||
const PoseidonHasher = await ethers.getContractFactory("PoseidonHasher");
|
||||
const poseidonHasher = await PoseidonHasher.deploy();
|
||||
|
||||
await poseidonHasher.deployed();
|
||||
|
||||
console.log("PoseidonHasher deployed to:", poseidonHasher.address);
|
||||
|
||||
const Rln = await ethers.getContractFactory("RLN");
|
||||
const rln = await Rln.deploy(1000000000000000,20,poseidonHasher.address);
|
||||
|
||||
await rln.deployed();
|
||||
|
||||
console.log("Rln deployed to:", rln.address);
|
||||
}
|
||||
|
||||
// We recommend this pattern to be able to use async/await everywhere
|
||||
// and properly handle errors.
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
import { assert } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
describe("Rln", function () {
|
||||
describe.skip("Rln", function () {
|
||||
it("Deploying", async function () {
|
||||
const PoseidonHasher = await ethers.getContractFactory("PoseidonHasher");
|
||||
const poseidonHasher = await PoseidonHasher.deploy();
|
||||
|
@ -1,21 +1,17 @@
|
||||
import { expect } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
import { ethers, deployments } from "hardhat";
|
||||
|
||||
describe("Rln", function () {
|
||||
it("Deploying", async function () {
|
||||
const PoseidonHasher = await ethers.getContractFactory("PoseidonHasher");
|
||||
const poseidonHasher = await PoseidonHasher.deploy();
|
||||
|
||||
await poseidonHasher.deployed();
|
||||
|
||||
console.log("PoseidonHasher deployed to:", poseidonHasher.address);
|
||||
describe("PoseidonHash", () => {
|
||||
beforeEach(async () => {
|
||||
await deployments.fixture(["PoseidonHasher"]);
|
||||
});
|
||||
|
||||
it("should hash correctly", async function () {
|
||||
const poseidonHasher = await ethers.getContract("PoseidonHasher");
|
||||
|
||||
// We test hashing for a random number
|
||||
const hash = await poseidonHasher.hash("19014214495641488759237505126948346942972912379615652741039992445865937985820");
|
||||
|
||||
console.log("Hash:", hash);
|
||||
|
||||
//Expect 0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368
|
||||
|
||||
expect(hash._hex).to.eql("0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368");
|
||||
});
|
||||
});
|
||||
|
@ -1,74 +1,15 @@
|
||||
import {expect} from "chai";
|
||||
import {Contract} from "ethers";
|
||||
import {ethers} from "hardhat";
|
||||
import {ethers, deployments} from "hardhat";
|
||||
import {sToBytes32, createGroupId} from '../common';
|
||||
|
||||
const sToBytes32 = (str: string): string => {
|
||||
return ethers.utils.formatBytes32String(str);
|
||||
}
|
||||
|
||||
const SNARK_SCALAR_FIELD = BigInt(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
||||
)
|
||||
|
||||
const createGroupId = (provider: string, name: string): bigint => {
|
||||
const providerBytes = sToBytes32(provider);
|
||||
const nameBytes = sToBytes32(name);
|
||||
return BigInt(ethers.utils.solidityKeccak256(["bytes32", "bytes32"], [providerBytes, nameBytes])) % SNARK_SCALAR_FIELD
|
||||
}
|
||||
|
||||
const providers = ['github', 'twitter', 'reddit'];
|
||||
const tiers = ['bronze', 'silver', 'gold'];
|
||||
|
||||
const getGroups = () => {
|
||||
return providers.flatMap(provider => tiers.map(tier => {
|
||||
return {
|
||||
provider: sToBytes32(provider),
|
||||
name: sToBytes32(tier),
|
||||
root: 1,
|
||||
depth: 10,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
const scaffoldInterep = async () => {
|
||||
// Deploy interep
|
||||
const InterepTest = await ethers.getContractFactory("InterepTest");
|
||||
const interepTest = await InterepTest.deploy();
|
||||
await interepTest.deployed();
|
||||
|
||||
// add all combinations of providers and tiers into an array
|
||||
const groups = getGroups();
|
||||
// insert groups into interep membership contract
|
||||
const groupInsertionTx = await interepTest.updateGroups(groups);
|
||||
await groupInsertionTx.wait();
|
||||
|
||||
return interepTest
|
||||
}
|
||||
|
||||
const scaffold = async () => {
|
||||
const interepTest = await scaffoldInterep();
|
||||
const interepAddress = interepTest.address;
|
||||
|
||||
// create valid group storage contract for rln
|
||||
const ValidGroupStorage = await ethers.getContractFactory("ValidGroupStorage");
|
||||
const groups = getGroups();
|
||||
const filteredGroups = groups
|
||||
.filter(group => group.name !== sToBytes32('bronze'));
|
||||
const validGroupStorage = await ValidGroupStorage.deploy(interepAddress, filteredGroups);
|
||||
await validGroupStorage.deployed();
|
||||
expect(validGroupStorage.address).to.not.equal(0);
|
||||
|
||||
return validGroupStorage
|
||||
}
|
||||
|
||||
describe("Valid Group Storage", () => {
|
||||
let validGroupStorage: Contract;
|
||||
beforeEach(async () => {
|
||||
validGroupStorage = await scaffold();
|
||||
await deployments.fixture(['InterepTest', 'ValidGroupStorage']);
|
||||
})
|
||||
|
||||
it('should not deploy if an invalid group is passed in constructor', async () => {
|
||||
const interepTest = await scaffoldInterep();
|
||||
const interepTest = await ethers.getContract('InterepTest');
|
||||
const interepAddress = interepTest.address;
|
||||
|
||||
const ValidGroupStorage = await ethers.getContractFactory("ValidGroupStorage");
|
||||
@ -79,11 +20,13 @@ describe("Valid Group Storage", () => {
|
||||
})
|
||||
|
||||
it("should return true for valid group", async () => {
|
||||
const validGroupStorage = await ethers.getContract('ValidGroupStorage');
|
||||
const valid = await validGroupStorage.isValidGroup(createGroupId('github', 'silver'));
|
||||
expect(valid).to.be.true;
|
||||
});
|
||||
|
||||
it("should return false for invalid group", async () => {
|
||||
const validGroupStorage = await ethers.getContract('ValidGroupStorage');
|
||||
const valid = await validGroupStorage.isValidGroup(createGroupId('github', 'bronze'));
|
||||
expect(valid).to.be.false;
|
||||
});
|
||||
|
@ -7,6 +7,13 @@
|
||||
"outDir": "dist",
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["./scripts", "./test", "./typechain"],
|
||||
"files": ["./hardhat.config.ts"]
|
||||
}
|
||||
"include": [
|
||||
"./scripts",
|
||||
"./test",
|
||||
"./typechain",
|
||||
"deploy"
|
||||
],
|
||||
"files": [
|
||||
"./hardhat.config.ts"
|
||||
]
|
||||
}
|
116
yarn.lock
116
yarn.lock
@ -730,10 +730,10 @@
|
||||
"@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0"
|
||||
"@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0"
|
||||
|
||||
"@nomiclabs/hardhat-ethers@^2.0.6":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.1.tgz#8057b43566a0e41abeb8142064a3c0d3f23dca86"
|
||||
integrity sha512-RHWYwnxryWR8hzRmU4Jm/q4gzvXpetUOJ4OPlwH2YARcDB+j79+yAYCwO0lN1SUOb4++oOTJEe6AWLEc42LIvg==
|
||||
"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers":
|
||||
version "0.3.0-beta.13"
|
||||
resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366"
|
||||
integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw==
|
||||
|
||||
"@nomiclabs/hardhat-etherscan@^3.1.0":
|
||||
version "3.1.2"
|
||||
@ -1116,7 +1116,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e"
|
||||
integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==
|
||||
|
||||
"@types/qs@^6.2.31":
|
||||
"@types/qs@^6.2.31", "@types/qs@^6.9.7":
|
||||
version "6.9.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
||||
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
|
||||
@ -1575,6 +1575,13 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
babel-code-frame@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
@ -2600,7 +2607,7 @@ chokidar@3.3.0:
|
||||
optionalDependencies:
|
||||
fsevents "~2.1.1"
|
||||
|
||||
chokidar@3.5.3, chokidar@^3.4.0:
|
||||
chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
@ -3007,7 +3014,7 @@ debug@3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3:
|
||||
debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
@ -3266,6 +3273,11 @@ emoji-regex@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
encode-utf8@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
|
||||
integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
@ -3296,7 +3308,7 @@ end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
enquirer@^2.3.0:
|
||||
enquirer@^2.3.0, enquirer@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
|
||||
integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
|
||||
@ -3875,7 +3887,7 @@ ethers@^4.0.32, ethers@^4.0.40:
|
||||
uuid "2.0.1"
|
||||
xmlhttprequest "1.8.0"
|
||||
|
||||
ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.6.9:
|
||||
ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3, ethers@^5.7.2:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
|
||||
integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
|
||||
@ -4198,7 +4210,14 @@ flow-stoplight@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b"
|
||||
integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA==
|
||||
|
||||
follow-redirects@^1.12.1:
|
||||
fmix@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c"
|
||||
integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==
|
||||
dependencies:
|
||||
imul "^1.0.0"
|
||||
|
||||
follow-redirects@^1.12.1, follow-redirects@^1.14.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
@ -4238,6 +4257,15 @@ form-data@^3.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||
@ -4285,6 +4313,15 @@ fs-extra@^0.30.0:
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs-extra@^10.0.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^4.0.2, fs-extra@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
|
||||
@ -4645,6 +4682,25 @@ har-validator@~5.1.3:
|
||||
ajv "^6.12.3"
|
||||
har-schema "^2.0.0"
|
||||
|
||||
hardhat-deploy@0.11.20:
|
||||
version "0.11.20"
|
||||
resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.20.tgz#d95499a0d29b75f1f1d3838c9a3eb6d2d0d20f57"
|
||||
integrity sha512-6G2aFLW0mfZxY0ljDf8rxzEJkVh57gr3Eia5H2DeBIQNJh0dhBV2Y5LDq4E4J9K4Crq0DjpxGNTshEtAB9eWxA==
|
||||
dependencies:
|
||||
"@types/qs" "^6.9.7"
|
||||
axios "^0.21.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.2"
|
||||
debug "^4.3.2"
|
||||
enquirer "^2.3.6"
|
||||
ethers "^5.5.3"
|
||||
form-data "^4.0.0"
|
||||
fs-extra "^10.0.0"
|
||||
match-all "^1.2.6"
|
||||
murmur-128 "^0.2.1"
|
||||
qs "^6.9.4"
|
||||
zksync-web3 "^0.8.1"
|
||||
|
||||
hardhat-gas-reporter@^1.0.8:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450"
|
||||
@ -4960,6 +5016,11 @@ immutable@^4.0.0-rc.12:
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==
|
||||
|
||||
imul@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9"
|
||||
integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==
|
||||
|
||||
indent-string@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||
@ -5501,6 +5562,15 @@ jsonfile@^4.0.0:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
dependencies:
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
|
||||
@ -5927,6 +5997,11 @@ markdown-table@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60"
|
||||
integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
|
||||
|
||||
match-all@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d"
|
||||
integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==
|
||||
|
||||
mcl-wasm@^0.7.1:
|
||||
version "0.7.9"
|
||||
resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f"
|
||||
@ -6314,6 +6389,15 @@ multihashes@^0.4.15, multihashes@~0.4.15:
|
||||
multibase "^0.7.0"
|
||||
varint "^5.0.0"
|
||||
|
||||
murmur-128@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d"
|
||||
integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==
|
||||
dependencies:
|
||||
encode-utf8 "^1.0.2"
|
||||
fmix "^0.1.0"
|
||||
imul "^1.0.0"
|
||||
|
||||
nano-json-stream-parser@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f"
|
||||
@ -7027,7 +7111,7 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@6.11.0, qs@^6.4.0, qs@^6.7.0:
|
||||
qs@6.11.0, qs@^6.4.0, qs@^6.7.0, qs@^6.9.4:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
@ -8569,6 +8653,11 @@ universalify@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
|
||||
unorm@^1.3.3:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af"
|
||||
@ -9584,3 +9673,8 @@ yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
zksync-web3@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14"
|
||||
integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw==
|
||||
|
Loading…
x
Reference in New Issue
Block a user