diff --git a/.env.example b/.env.example index dbba210..a7105e0 100644 --- a/.env.example +++ b/.env.example @@ -1,13 +1,11 @@ -export INFURA_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export MNEMONIC="adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise father hope layer" -export PRIVATE_KEY_ORACLE_DEPLOYER="717fd99986df414889fd8b51069d4f90a50af72e542c58ee065f5883779099c6" -export PRIVATE_KEY_ORACLE_OWNER="717fd99986df414889fd8b51069d4f90a50af72e542c58ee065f5883779099c6" -export PRIVATE_KEY_ORACLE_RELAYER="7ec931411ad75a7c201469a385d6f18a325d4923f9f213bd882bbea87e160b67" +export MNEMONIC="exchange vintage ocean narrow danger return culture ignore trim solve clock hidden buddy wise emotion" +export PRIVATE_KEY_FHEVM_DEPLOYER="f2caf1b49a8f33e5a95fc55b0903daddd261d5a874ff154dc5d809a5f1c90449" +export PRIVATE_KEY_GATEWAY_DEPLOYER="e956ca0c96995551256523af64ac2f134c6b65d3e9d5c7b24ac4cd0a12f07bfd" +export PRIVATE_KEY_GATEWAY_RELAYER="049bdaae72bcc269f5edf17be5a01d61374e139b425984431242a3a74f73e92a" +export NUM_KMS_SIGNERS="1" +export PRIVATE_KEY_KMS_SIGNER_0="d5b160a52fe6015861d0a1bea9523aaab3699d52af8f3cede5fcdbdfdd4c77cc" +export PRIVATE_KEY_COPROCESSOR_ACCOUNT="83e0173b9d07abd53958da9f417df515b0957c4f8afd7171b518d192b52ae313" +export IS_COPROCESSOR="true" -# Block explorer API keys -export ARBISCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export BSCSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export ETHERSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export OPTIMISM_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export POLYGONSCAN_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" -export SNOWTRACE_API_KEY="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" \ No newline at end of file +export SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +export ETHERSCAN_API_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e91e59..7a487b4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,11 +1,11 @@ name: Pull request tests on: - pull_request: + push: branches: - main jobs: build: - runs-on: large_ubuntu_16 + runs-on: ubuntu-latest strategy: matrix: node-version: diff --git a/.github/workflows/testmock.yml b/.github/workflows/testmock.yml index bb5670f..b1c36f0 100644 --- a/.github/workflows/testmock.yml +++ b/.github/workflows/testmock.yml @@ -5,7 +5,7 @@ on: - main jobs: build: - runs-on: large_ubuntu_16 + runs-on: ubuntu-latest strategy: matrix: node-version: diff --git a/.gitignore b/.gitignore index 4aba7c5..73ddb24 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ dist node_modules types deployments +kms-fhe-keys/ +network-fhe-keys/ +fhevmTemp/ +abi/ # files *.env @@ -18,4 +22,9 @@ deployments .pnp.* coverage.json package-lock.json -yarn.lock \ No newline at end of file +yarn.lock + +res/ +running_node/ + +docker-compose/docker-compose-full.yml diff --git a/.npmignore b/.npmignore index 469a7e6..581c0be 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,4 @@ * -!contracts/** !package.json !README.md !LICENSE diff --git a/.prettierrc.yml b/.prettierrc.yml index 42ad8c5..56221e3 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -11,7 +11,7 @@ trailingComma: "all" overrides: - files: "*.sol" options: - compiler: "0.8.22" + compiler: "0.8.24" parser: "solidity-parse" tabWidth: 4 - files: "*.ts" diff --git a/.solcover.js b/.solcover.js index d71a669..1834226 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,7 +1,9 @@ -module.exports = { - istanbulReporter: ["html", "lcov"], - providerOptions: { - mnemonic: process.env.MNEMONIC, - }, - skipFiles: ["test"], +export const istanbulReporter = ["html", "lcov"]; +export const providerOptions = { + mnemonic: process.env.MNEMONIC, +}; +export const skipFiles = ["test", "fhevmTemp"]; +export const mocha = { + fgrep: "[skip-on-coverage]", + invert: true, }; diff --git a/.solhint.json b/.solhint.json index 122f1f6..c80271f 100644 --- a/.solhint.json +++ b/.solhint.json @@ -3,11 +3,17 @@ "plugins": ["prettier"], "rules": { "code-complexity": ["error", 8], - "compiler-version": ["error", ">=0.8.4"], - "func-visibility": ["error", { "ignoreConstructors": true }], + "compiler-version": ["error", ">=0.8.24"], + "func-visibility": [ + "error", + { + "ignoreConstructors": true + } + ], "max-line-length": ["error", 120], "named-parameters-mapping": "warn", "no-console": "off", + "no-global-import": "off", "not-rely-on-time": "off", "prettier/prettier": [ "error", diff --git a/CustomProvider.ts b/CustomProvider.ts new file mode 100644 index 0000000..b60308e --- /dev/null +++ b/CustomProvider.ts @@ -0,0 +1,62 @@ +import { ethers } from "ethers"; +import { ProviderWrapper } from "hardhat/plugins"; +import type { EIP1193Provider, RequestArguments } from "hardhat/types"; + +interface Test { + request: EIP1193Provider["request"]; +} + +class CustomProvider extends ProviderWrapper implements Test { + public lastBlockSnapshot: number; + public lastCounterRand: number; + public lastBlockSnapshotForDecrypt: number; + + constructor(protected readonly _wrappedProvider: EIP1193Provider) { + super(_wrappedProvider); + this.lastBlockSnapshot = 0; // Initialize the variable + this.lastCounterRand = 0; + this.lastBlockSnapshotForDecrypt = 0; + } + + async request(args: RequestArguments): ReturnType { + if (args.method === "eth_estimateGas") { + const estimatedGasLimit = BigInt((await this._wrappedProvider.request(args)) as bigint); + const increasedGasLimit = ethers.toBeHex((estimatedGasLimit * 120n) / 100n); // override estimated gasLimit by 120%, to avoid some edge case with ethermint gas estimation + return increasedGasLimit; + } + if (args.method === "evm_revert") { + const result = await this._wrappedProvider.request(args); + const blockNumberHex = (await this._wrappedProvider.request({ method: "eth_blockNumber" })) as string; + this.lastBlockSnapshot = parseInt(blockNumberHex); + this.lastBlockSnapshotForDecrypt = parseInt(blockNumberHex); + + const callData = { + to: "0x000000000000000000000000000000000000005d", + data: "0x1f20d85c", + }; + this.lastCounterRand = (await this._wrappedProvider.request({ + method: "eth_call", + params: [callData, "latest"], + })) as number; + return result; + } + if (args.method === "get_lastBlockSnapshot") { + return [this.lastBlockSnapshot, this.lastCounterRand]; + } + if (args.method === "get_lastBlockSnapshotForDecrypt") { + return this.lastBlockSnapshotForDecrypt; + } + if (args.method === "set_lastBlockSnapshot") { + this.lastBlockSnapshot = Array.isArray(args.params!) && args.params[0]; + return this.lastBlockSnapshot; + } + if (args.method === "set_lastBlockSnapshotForDecrypt") { + this.lastBlockSnapshotForDecrypt = Array.isArray(args.params!) && args.params[0]; + return this.lastBlockSnapshotForDecrypt; + } + const result = this._wrappedProvider.request(args); + return result; + } +} + +export default CustomProvider; diff --git a/README.md b/README.md index 4c5b7c6..e8615e6 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ pnpm add fhevm-contracts ```solidity // SPDX-License-Identifier: BSD-3-Clause-Clear -pragma solidity ^0.8.20; +pragma solidity ^0.8.24; import "fhevm/lib/TFHE.sol"; import "fhevm-contracts/contracts/token/ERC20/EncryptedERC20.sol"; diff --git a/contracts/DAO/Comp.sol b/contracts/DAO/Comp.sol deleted file mode 100644 index f221ec1..0000000 --- a/contracts/DAO/Comp.sol +++ /dev/null @@ -1,259 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.20; - -import "fhevm/abstracts/Reencrypt.sol"; -import "fhevm/lib/TFHE.sol"; -import "../token/ERC20/EncryptedERC20.sol"; -import "@openzeppelin/contracts/access/Ownable2Step.sol"; - -contract Comp is EncryptedERC20, Ownable2Step { - /// @notice allowed smart contract - address public allowedContract; - - /// @notice A record of each accounts delegate - mapping(address => address) public delegates; - - /// @notice A checkpoint for marking number of votes from a given block - struct Checkpoint { - uint32 fromBlock; - euint64 votes; - } - - /// @notice A record of votes checkpoints for each account, by index - mapping(address => mapping(uint32 => Checkpoint)) internal checkpoints; - - /// @notice The number of checkpoints for each account - mapping(address => uint32) public numCheckpoints; - - /// @notice The EIP-712 typehash for the contract's domain - bytes32 public constant DOMAIN_TYPEHASH = - keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); - - /// @notice The EIP-712 typehash for the delegation struct used by the contract - bytes32 public constant DELEGATION_TYPEHASH = - keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); - - /// @notice A record of states for signing / validating signatures - mapping(address => uint256) public nonces; - - /// @notice An event thats emitted when an account changes its delegate - event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); - - /// @notice An event thats emitted when a delegate account's vote balance changes - event DelegateVotesChanged(address indexed delegate); - - /** - * @notice Construct a new Comp token - */ - constructor(address account) EncryptedERC20("Compound", "COMP") Ownable(account) { - _mint(10000000e6, account); // 10 million Comp - } - - /** - * @notice Set allowed contract that can access votes - * @param contractAddress The address of the smart contract which may access votes - */ - function setAllowedContract(address contractAddress) public onlyOwner { - allowedContract = contractAddress; - } - - function _moveDelegates(address srcRep, address dstRep, euint64 amount) internal { - if (srcRep != dstRep) { - if (srcRep != address(0)) { - uint32 srcRepNum = numCheckpoints[srcRep]; - euint64 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : TFHE.asEuint64(0); - euint64 srcRepNew = srcRepOld - amount; - _writeCheckpoint(srcRep, srcRepNum, srcRepNew); - } - - if (dstRep != address(0)) { - uint32 dstRepNum = numCheckpoints[dstRep]; - euint64 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : TFHE.asEuint64(0); - euint64 dstRepNew = dstRepOld + amount; - _writeCheckpoint(dstRep, dstRepNum, dstRepNew); - } - } - } - - function _writeCheckpoint(address delegatee, uint32 nCheckpoints, euint64 newVotes) internal { - uint32 blockNumber = safe32(block.number, "Comp::_writeCheckpoint: block number exceeds 32 bits"); - - if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { - checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; - } else { - checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); - numCheckpoints[delegatee] = nCheckpoints + 1; - } - - emit DelegateVotesChanged(delegatee); - } - - /** - * @notice Delegate votes from `msg.sender` to `delegatee` - * @param delegatee The address to delegate votes to - */ - function delegate(address delegatee) public { - return _delegate(msg.sender, delegatee); - } - - function _transfer( - address from, - address to, - euint64 amount, - ebool isTransferable, - euint8 errorCode - ) internal override { - require(from != address(0), "Comp::_transferTokens: cannot transfer from the zero address"); - require(to != address(0), "Comp::_transferTokens: cannot transfer to the zero address"); - // Add to the balance of `to` and subract from the balance of `from`. - euint64 amountTransferred = TFHE.select(isTransferable, amount, TFHE.asEuint64(0)); - balances[to] = balances[to] + amountTransferred; - balances[from] = balances[from] - amountTransferred; - uint256 transferId = saveError(errorCode); - emit Transfer(transferId, from, to); - AllowedErrorReencryption memory allowedErrorReencryption = AllowedErrorReencryption( - msg.sender, - getError(transferId) - ); - allowedErrorReencryptions[transferId] = allowedErrorReencryption; - _moveDelegates(delegates[from], delegates[to], amountTransferred); - } - - /** - * @notice Delegates votes from signatory to `delegatee` - * @param delegatee The address to delegate votes to - * @param nonce The contract state required to match the signature - * @param expiry The time at which to expire the signature - * @param v The recovery byte of the signature - * @param r Half of the ECDSA signature pair - * @param s Half of the ECDSA signature pair - */ - function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) public { - bytes32 domainSeparator = keccak256( - abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), getChainId(), address(this)) - ); - bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); - address signatory = ecrecover(digest, v, r, s); - require(signatory != address(0), "Comp::delegateBySig: invalid signature"); - require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce"); - require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired"); - return _delegate(signatory, delegatee); - } - - function getMyCurrentVotes( - bytes32 publicKey, - bytes calldata signature - ) external view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - uint32 nCheckpoints = numCheckpoints[msg.sender]; - euint64 result = nCheckpoints > 0 ? checkpoints[msg.sender][nCheckpoints - 1].votes : TFHE.asEuint64(0); - return TFHE.reencrypt(result, publicKey, 0); - } - - /** - * @notice Determine the prior number of votes for an account as of a block number - * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. - * @param account The address of the account to check - * @param blockNumber The block number to get the vote balance at - * @return The number of votes the account had as of the given block - */ - function getPriorVotes(address account, uint256 blockNumber) external view onlyAllowedContract returns (euint64) { - require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined"); - - uint32 nCheckpoints = numCheckpoints[account]; - if (nCheckpoints == 0) { - return TFHE.asEuint64(0); - } - - // First check most recent balance - if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { - return checkpoints[account][nCheckpoints - 1].votes; - } - - // Next check implicit zero balance - if (checkpoints[account][0].fromBlock > blockNumber) { - return TFHE.asEuint64(0); - } - - uint32 lower = 0; - uint32 upper = nCheckpoints - 1; - while (upper > lower) { - uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow - Checkpoint memory cp = checkpoints[account][center]; - if (cp.fromBlock == blockNumber) { - return cp.votes; - } else if (cp.fromBlock < blockNumber) { - lower = center; - } else { - upper = center - 1; - } - } - return checkpoints[account][lower].votes; - } - - function getMyPriorVotes( - uint256 blockNumber, - bytes32 publicKey, - bytes calldata signature - ) public view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined"); - - uint32 nCheckpoints = numCheckpoints[msg.sender]; - euint64 result; - if (nCheckpoints == 0) { - return TFHE.reencrypt(result, publicKey, 0); - } - - // First check most recent balance - if (checkpoints[msg.sender][nCheckpoints - 1].fromBlock <= blockNumber) { - result = checkpoints[msg.sender][nCheckpoints - 1].votes; - return TFHE.reencrypt(result, publicKey, 0); - } - - // Next check implicit zero balance - if (checkpoints[msg.sender][0].fromBlock > blockNumber) { - return TFHE.reencrypt(result, publicKey, 0); - } - - uint32 lower = 0; - uint32 upper = nCheckpoints - 1; - while (upper > lower) { - uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow - Checkpoint memory cp = checkpoints[msg.sender][center]; - if (cp.fromBlock == blockNumber) { - result = cp.votes; - return TFHE.reencrypt(result, publicKey, 0); - } else if (cp.fromBlock < blockNumber) { - lower = center; - } else { - upper = center - 1; - } - } - result = checkpoints[msg.sender][lower].votes; - return TFHE.reencrypt(result, publicKey, 0); - } - - function _delegate(address delegator, address delegatee) internal { - address currentDelegate = delegates[delegator]; - euint64 delegatorBalance = balances[delegator]; - delegates[delegator] = delegatee; - - emit DelegateChanged(delegator, currentDelegate, delegatee); - - _moveDelegates(currentDelegate, delegatee, delegatorBalance); - } - - function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) { - require(n < 2 ** 32, errorMessage); - return uint32(n); - } - - function getChainId() internal view returns (uint256) { - return block.chainid; - } - - modifier onlyAllowedContract() { - require(msg.sender == allowedContract, "Caller not allowed to call this function"); - _; - } -} diff --git a/contracts/DAO/GovernorZama.sol b/contracts/DAO/GovernorZama.sol deleted file mode 100644 index acfb61a..0000000 --- a/contracts/DAO/GovernorZama.sol +++ /dev/null @@ -1,466 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.20; - -import "fhevm/abstracts/Reencrypt.sol"; -import "fhevm/lib/TFHE.sol"; - -contract GovernorZama is Reencrypt { - /// @notice The name of this contract - string public constant name = "Compound Governor Zama"; - - uint32 public immutable VOTING_PERIOD; // Duration of voting in number of blocks, typically should by at least a few days, default was 3 days originally ~21600 blocks if 12s per block - // WARNING: do not use too small value in production such as 5 or a few dozens to avoid security issues, unless for testing purpose - - /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed - function quorumVotes() public pure returns (uint256) { - return 400000e6; - } // 400,000 = 4% of Comp - - /// @notice The number of votes required in order for a voter to become a proposer - function proposalThreshold() public pure returns (uint64) { - return 100000e6; - } // 100,000 = 1% of Comp - - /// @notice The maximum number of actions that can be included in a proposal - function proposalMaxOperations() public pure returns (uint32) { - return 10; - } // 10 actions - - /// @notice The delay before voting on a proposal may take place, once proposed - function votingDelay() public pure returns (uint32) { - return 1; - } // 1 block - - /// @notice The duration of voting on a proposal, in blocks - function votingPeriod() public view virtual returns (uint32) { - return VOTING_PERIOD; - } // recommended 3 days in blocks, i.e 21600 (assuming 12s blocks) - - /// @notice The address of the Compound Protocol Timelock - TimelockInterface public timelock; - - /// @notice The address of the Compound governance token - CompInterface public comp; - - /// @notice The address of the Governor Guardian - address public guardian; - - /// @notice The total number of proposals - uint256 public proposalCount; - - struct Proposal { - /// @notice Unique id for looking up a proposal - uint256 id; - /// @notice Creator of the proposal - address proposer; - /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds - uint256 eta; - /// @notice the ordered list of target addresses for calls to be made - address[] targets; - /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made - uint256[] values; - /// @notice The ordered list of function signatures to be called - string[] signatures; - /// @notice The ordered list of calldata to be passed to each call - bytes[] calldatas; - /// @notice The block at which voting begins: holders must delegate their votes prior to this block - uint256 startBlock; - /// @notice The block at which voting ends: votes must be cast prior to this block - uint256 endBlock; - /// @notice Current number of votes in favor of this proposal - euint64 forVotes; - /// @notice Current number of votes in opposition to this proposal - euint64 againstVotes; - /// @notice Flag marking whether the proposal has been canceled - bool canceled; - /// @notice Flag marking whether the proposal has been executed - bool executed; - /// @notice Receipts of ballots for the entire set of voters - mapping(address => Receipt) receipts; - } - - struct ProposalInfo { - /// @notice Unique id for looking up a proposal - uint256 id; - /// @notice Creator of the proposal - address proposer; - /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds - uint256 eta; - /// @notice the ordered list of target addresses for calls to be made - address[] targets; - /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made - uint256[] values; - /// @notice The ordered list of function signatures to be called - string[] signatures; - /// @notice The ordered list of calldata to be passed to each call - bytes[] calldatas; - /// @notice The block at which voting begins: holders must delegate their votes prior to this block - uint256 startBlock; - /// @notice The block at which voting ends: votes must be cast prior to this block - uint256 endBlock; - /// @notice Flag marking whether the proposal has been canceled - bool canceled; - /// @notice Flag marking whether the proposal has been executed - bool executed; - } - - /// @notice Ballot receipt record for a voter - struct Receipt { - /// @notice Whether or not a vote has been cast - bool hasVoted; - /// @notice Whether or not the voter supports the proposal - ebool support; - /// @notice The number of votes the voter had, which were cast - euint64 votes; - } - - /// @notice Possible states that a proposal may be in - enum ProposalState { - Pending, - Active, - Canceled, - Defeated, - Succeeded, - Queued, - Expired, - Executed - } - - /// @notice The official record of all proposals ever proposed - mapping(uint256 => Proposal) internal proposals; - - /// @notice The latest proposal for each proposer - mapping(address => uint256) public latestProposalIds; - - /// @notice An event emitted when a new proposal is created - event ProposalCreated( - uint256 id, - address proposer, - address[] targets, - uint256[] values, - string[] signatures, - bytes[] calldatas, - uint256 startBlock, - uint256 endBlock, - string description - ); - - /// @notice An event emitted when a vote has been cast on a proposal - event VoteCast(address voter, uint256 proposalId); - - /// @notice An event emitted when a proposal has been canceled - event ProposalCanceled(uint256 id); - - /// @notice An event emitted when a proposal has been queued in the Timelock - event ProposalQueued(uint256 id, uint256 eta); - - /// @notice An event emitted when a proposal has been executed in the Timelock - event ProposalExecuted(uint256 id); - - constructor(address timelock_, address comp_, address guardian_, uint32 _votingPeriod) { - timelock = TimelockInterface(timelock_); - comp = CompInterface(comp_); - guardian = guardian_; - VOTING_PERIOD = _votingPeriod; // WARNING: do not use too small value in production such as 5 or a few dozens to avoid security issues, unless for testing purpose, typically should by at least a few days, default was 3 days originally i.e votingPeriod=21600 blocks if 12s per block - } - - function propose( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas, - string memory description - ) public returns (uint256) { - require( - TFHE.decrypt(TFHE.lt(proposalThreshold(), comp.getPriorVotes(msg.sender, block.number - 1))), - "GovernorAlpha::propose: proposer votes below proposal threshold" - ); - require( - targets.length == values.length && - targets.length == signatures.length && - targets.length == calldatas.length, - "GovernorAlpha::propose: proposal function information arity mismatch" - ); - require(targets.length != 0, "GovernorAlpha::propose: must provide actions"); - require(targets.length <= proposalMaxOperations(), "GovernorAlpha::propose: too many actions"); - - uint256 latestProposalId = latestProposalIds[msg.sender]; - if (latestProposalId != 0) { - ProposalState proposersLatestProposalState = state(latestProposalId); - require( - proposersLatestProposalState != ProposalState.Active, - "GovernorAlpha::propose: one live proposal per proposer, found an already active proposal" - ); - require( - proposersLatestProposalState != ProposalState.Pending, - "GovernorAlpha::propose: one live proposal per proposer, found an already pending proposal" - ); - } - - uint256 startBlock = block.number + votingDelay(); - uint256 endBlock = startBlock + votingPeriod(); - - proposalCount++; - uint256 proposalId = proposalCount; - Proposal storage newProposal = proposals[proposalId]; - - newProposal.id = proposalId; - newProposal.proposer = msg.sender; - newProposal.eta = 0; - newProposal.targets = targets; - newProposal.values = values; - newProposal.signatures = signatures; - newProposal.forVotes = TFHE.asEuint64(0); - newProposal.againstVotes = TFHE.asEuint64(0); - newProposal.calldatas = calldatas; - newProposal.startBlock = startBlock; - newProposal.endBlock = endBlock; - newProposal.canceled = false; - newProposal.executed = false; - - latestProposalIds[newProposal.proposer] = newProposal.id; - - emit ProposalCreated( - newProposal.id, - msg.sender, - targets, - values, - signatures, - calldatas, - startBlock, - endBlock, - description - ); - return newProposal.id; - } - - function queue(uint256 proposalId) public { - require( - state(proposalId) == ProposalState.Succeeded, - "GovernorAlpha::queue: proposal can only be queued if it is succeeded" - ); - Proposal storage proposal = proposals[proposalId]; - uint256 eta = block.timestamp + timelock.delay(); - - for (uint256 i = 0; i < proposal.targets.length; i++) { - _queueOrRevert(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], eta); - } - proposal.eta = eta; - emit ProposalQueued(proposalId, eta); - } - - function _queueOrRevert( - address target, - uint256 value, - string memory signature, - bytes memory data, - uint256 eta - ) internal { - require( - !timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), - "GovernorAlpha::_queueOrRevert: proposal action already queued at eta" - ); - timelock.queueTransaction(target, value, signature, data, eta); - } - - function execute(uint256 proposalId) public payable { - require( - state(proposalId) == ProposalState.Queued, - "GovernorAlpha::execute: proposal can only be executed if it is queued" - ); - Proposal storage proposal = proposals[proposalId]; - proposal.executed = true; - for (uint256 i = 0; i < proposal.targets.length; i++) { - timelock.executeTransaction{ value: proposal.values[i] }( - proposal.targets[i], - proposal.values[i], - proposal.signatures[i], - proposal.calldatas[i], - proposal.eta - ); - } - emit ProposalExecuted(proposalId); - } - - function cancel(uint256 proposalId) public { - ProposalState proposalState = state(proposalId); - require(proposalState != ProposalState.Executed, "GovernorAlpha::cancel: cannot cancel executed proposal"); - - Proposal storage proposal = proposals[proposalId]; - - ebool proposerAboveThreshold = TFHE.lt(proposalThreshold(), comp.getPriorVotes(msg.sender, block.number - 1)); - - require(msg.sender == guardian || TFHE.decrypt(proposerAboveThreshold)); - - proposal.canceled = true; - for (uint256 i = 0; i < proposal.targets.length; i++) { - timelock.cancelTransaction( - proposal.targets[i], - proposal.values[i], - proposal.signatures[i], - proposal.calldatas[i], - proposal.eta - ); - } - - emit ProposalCanceled(proposalId); - } - - function getActions( - uint256 proposalId - ) - public - view - returns ( - address[] memory targets, - uint256[] memory values, - string[] memory signatures, - bytes[] memory calldatas - ) - { - Proposal storage p = proposals[proposalId]; - return (p.targets, p.values, p.signatures, p.calldatas); - } - - function getMyReceipt( - uint256 proposalId, - bytes32 publicKey, - bytes calldata signature - ) external view onlySignedPublicKey(publicKey, signature) returns (bool, bytes memory, bytes memory) { - Receipt memory myReceipt = proposals[proposalId].receipts[msg.sender]; - return ( - myReceipt.hasVoted, - TFHE.reencrypt(myReceipt.support, publicKey, false), - TFHE.reencrypt(myReceipt.votes, publicKey, 0) - ); - } - - function getProposalInfo(uint256 proposalId) external view returns (ProposalInfo memory propInfo) { - require(proposalId <= proposalCount && proposalId != 0, "Invalid proposalId"); - Proposal storage proposal = proposals[proposalId]; - propInfo.id = proposal.id; - propInfo.proposer = proposal.proposer; - propInfo.eta = proposal.eta; - propInfo.targets = proposal.targets; - propInfo.values = proposal.values; - propInfo.signatures = proposal.signatures; - propInfo.calldatas = proposal.calldatas; - propInfo.startBlock = proposal.startBlock; - propInfo.endBlock = proposal.endBlock; - propInfo.canceled = proposal.canceled; - propInfo.executed = proposal.executed; - } - - function isDefeated(Proposal storage proposal) private view returns (bool) { - ebool defeated = TFHE.le(proposal.forVotes, proposal.againstVotes); - ebool notReachedQuorum = TFHE.lt(proposal.forVotes, uint64(quorumVotes())); - - return TFHE.decrypt(TFHE.or(notReachedQuorum, defeated)); - } - - function state(uint256 proposalId) public view returns (ProposalState) { - require(proposalCount >= proposalId && proposalId > 0, "GovernorAlpha::state: invalid proposal id"); - Proposal storage proposal = proposals[proposalId]; - if (proposal.canceled) { - return ProposalState.Canceled; - } else if (block.number <= proposal.startBlock) { - return ProposalState.Pending; - } else if (block.number <= proposal.endBlock) { - return ProposalState.Active; - } else if (isDefeated(proposal)) { - return ProposalState.Defeated; - } else if (proposal.eta == 0) { - return ProposalState.Succeeded; - } else if (proposal.executed) { - return ProposalState.Executed; - } else if (block.timestamp >= proposal.eta + timelock.GRACE_PERIOD()) { - return ProposalState.Expired; - } else { - return ProposalState.Queued; - } - } - - function castVote(uint256 proposalId, bytes calldata support) public { - return castVote(proposalId, TFHE.asEbool(support)); - } - - function castVote(uint256 proposalId, ebool support) public { - return _castVote(msg.sender, proposalId, support); - } - - function _castVote(address voter, uint256 proposalId, ebool support) internal { - require(state(proposalId) == ProposalState.Active, "GovernorAlpha::_castVote: voting is closed"); - Proposal storage proposal = proposals[proposalId]; - Receipt storage receipt = proposal.receipts[voter]; - require(receipt.hasVoted == false, "GovernorAlpha::_castVote: voter already voted"); - euint64 votes = comp.getPriorVotes(voter, proposal.startBlock); - - proposal.forVotes = TFHE.select(support, proposal.forVotes + votes, proposal.forVotes); - proposal.againstVotes = TFHE.select(support, proposal.againstVotes, proposal.againstVotes + votes); - - receipt.hasVoted = true; - receipt.support = support; - receipt.votes = votes; - - // `support` and `votes` are encrypted values, no need to include them in the event. - emit VoteCast(voter, proposalId); - } - - function __acceptAdmin() public { - require(msg.sender == guardian, "GovernorAlpha::__acceptAdmin: sender must be gov guardian"); - timelock.acceptAdmin(); - } - - function __abdicate() public { - require(msg.sender == guardian, "GovernorAlpha::__abdicate: sender must be gov guardian"); - guardian = address(0); - } - - function __queueSetTimelockPendingAdmin(address newPendingAdmin, uint256 eta) public { - require(msg.sender == guardian, "GovernorAlpha::__queueSetTimelockPendingAdmin: sender must be gov guardian"); - timelock.queueTransaction(address(timelock), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); - } - - function __executeSetTimelockPendingAdmin(address newPendingAdmin, uint256 eta) public { - require(msg.sender == guardian, "GovernorAlpha::__executeSetTimelockPendingAdmin: sender must be gov guardian"); - timelock.executeTransaction(address(timelock), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); - } -} - -interface TimelockInterface { - function delay() external view returns (uint256); - - function GRACE_PERIOD() external view returns (uint256); - - function acceptAdmin() external; - - function queuedTransactions(bytes32 hash) external view returns (bool); - - function queueTransaction( - address target, - uint256 value, - string calldata signature, - bytes calldata data, - uint256 eta - ) external returns (bytes32); - - function cancelTransaction( - address target, - uint256 value, - string calldata signature, - bytes calldata data, - uint256 eta - ) external; - - function executeTransaction( - address target, - uint256 value, - string calldata signature, - bytes calldata data, - uint256 eta - ) external payable returns (bytes memory); -} - -interface CompInterface { - function getPriorVotes(address account, uint256 blockNumber) external view returns (euint64); -} diff --git a/contracts/asyncDecrypt/TestAsyncDecrypt.sol b/contracts/asyncDecrypt/TestAsyncDecrypt.sol deleted file mode 100644 index 05376ad..0000000 --- a/contracts/asyncDecrypt/TestAsyncDecrypt.sol +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.20; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/oracle/OracleCaller.sol"; - -contract TestAsyncDecrypt is OracleCaller { - ebool xBool; - euint4 xUint4; - euint8 xUint8; - euint16 xUint16; - euint32 xUint32; - euint64 xUint64; - eaddress xAddress; - - bool public yBool; - uint8 public yUint4; - uint8 public yUint8; - uint16 public yUint16; - uint32 public yUint32; - uint64 public yUint64; - address public yAddress; - - constructor() { - xBool = TFHE.asEbool(true); - xUint4 = TFHE.asEuint4(4); - xUint8 = TFHE.asEuint8(42); - xUint16 = TFHE.asEuint16(16); - xUint32 = TFHE.asEuint32(32); - xUint64 = TFHE.asEuint64(64); - xAddress = TFHE.asEaddress(0x8ba1f109551bD432803012645Ac136ddd64DBA72); - } - - function requestBoolAboveDelay() public { - // should revert - ebool[] memory cts = new ebool[](1); - cts[0] = xBool; - Oracle.requestDecryption(cts, this.callbackBool.selector, 0, block.timestamp + 2 days); - } - - function requestBool() public { - ebool[] memory cts = new ebool[](1); - cts[0] = xBool; - Oracle.requestDecryption(cts, this.callbackBool.selector, 0, block.timestamp + 100); - } - - function requestFakeBool() public { - ebool[] memory cts = new ebool[](1); - cts[0] = ebool.wrap(42); - Oracle.requestDecryption(cts, this.callbackBool.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackBool(uint256 /*requestID*/, bool decryptedInput) public onlyOracle returns (bool) { - yBool = decryptedInput; - return yBool; - } - - function requestUint4() public { - euint4[] memory cts = new euint4[](1); - cts[0] = xUint4; - Oracle.requestDecryption(cts, this.callbackUint4.selector, 0, block.timestamp + 100); - } - - function requestFakeUint4() public { - euint4[] memory cts = new euint4[](1); - cts[0] = euint4.wrap(42); - Oracle.requestDecryption(cts, this.callbackUint4.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackUint4(uint256 /*requestID*/, uint8 decryptedInput) public onlyOracle returns (uint8) { - yUint4 = decryptedInput; - return decryptedInput; - } - - function requestUint8() public { - euint8[] memory cts = new euint8[](1); - cts[0] = xUint8; - Oracle.requestDecryption(cts, this.callbackUint8.selector, 0, block.timestamp + 100); - } - - function requestFakeUint8() public { - euint8[] memory cts = new euint8[](1); - cts[0] = euint8.wrap(42); - Oracle.requestDecryption(cts, this.callbackUint8.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackUint8(uint256 /*requestID*/, uint8 decryptedInput) public onlyOracle returns (uint8) { - yUint8 = decryptedInput; - return decryptedInput; - } - - function requestUint16() public { - euint16[] memory cts = new euint16[](1); - cts[0] = xUint16; - Oracle.requestDecryption(cts, this.callbackUint16.selector, 0, block.timestamp + 100); - } - - function requestFakeUint16() public { - euint16[] memory cts = new euint16[](1); - cts[0] = euint16.wrap(42); - Oracle.requestDecryption(cts, this.callbackUint16.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackUint16(uint256 /*requestID*/, uint16 decryptedInput) public onlyOracle returns (uint16) { - yUint16 = decryptedInput; - return decryptedInput; - } - - function requestUint32(uint32 input1, uint32 input2) public { - euint32[] memory cts = new euint32[](1); - cts[0] = xUint32; - uint256 requestID = Oracle.requestDecryption(cts, this.callbackUint32.selector, 0, block.timestamp + 100); - addParamsUint(requestID, input1); - addParamsUint(requestID, input2); - } - - function requestFakeUint32() public { - euint32[] memory cts = new euint32[](1); - cts[0] = euint32.wrap(42); - Oracle.requestDecryption(cts, this.callbackUint32.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackUint32(uint256 requestID, uint32 decryptedInput) public onlyOracle returns (uint32) { - uint256[] memory params = getParamsUint(requestID); - unchecked { - uint32 result = uint32(params[0]) + uint32(params[1]) + decryptedInput; - yUint32 = result; - return result; - } - } - - function requestUint64() public { - euint64[] memory cts = new euint64[](1); - cts[0] = xUint64; - Oracle.requestDecryption(cts, this.callbackUint64.selector, 0, block.timestamp + 100); - } - - function requestFakeUint64() public { - euint64[] memory cts = new euint64[](1); - cts[0] = euint64.wrap(42); - Oracle.requestDecryption(cts, this.callbackUint64.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackUint64(uint256 /*requestID*/, uint64 decryptedInput) public onlyOracle returns (uint64) { - yUint64 = decryptedInput; - return decryptedInput; - } - - function requestAddress() public { - eaddress[] memory cts = new eaddress[](1); - cts[0] = xAddress; - Oracle.requestDecryption(cts, this.callbackAddress.selector, 0, block.timestamp + 100); - } - - function requestFakeAddress() public { - eaddress[] memory cts = new eaddress[](1); - cts[0] = eaddress.wrap(42); - Oracle.requestDecryption(cts, this.callbackAddress.selector, 0, block.timestamp + 100); // this should revert because previous ebool is not honestly obtained - } - - function callbackAddress(uint256 /*requestID*/, address decryptedInput) public onlyOracle returns (address) { - yAddress = decryptedInput; - return decryptedInput; - } -} diff --git a/contracts/governance/Comp.sol b/contracts/governance/Comp.sol new file mode 100644 index 0000000..49499f4 --- /dev/null +++ b/contracts/governance/Comp.sol @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import { Ownable2Step, Ownable } from "@openzeppelin/contracts/access/Ownable2Step.sol"; +import { EncryptedERC20 } from "../token/ERC20/EncryptedERC20.sol"; +import { IComp } from "./IComp.sol"; + +/** + * @title Comp + * @notice This contract inherits EncryptedERC20 and Ownable2Step. + * This is based on the Comp.sol contract written by Compound Labs. + * see: compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol + * It is a governance token used to delegate votes, which can be used by contracts such as + * GovernorAlphaZama.sol. + * It uses encrypted votes to delegate the voting power associated + * with an account's balance. + * @dev The delegation of votes leaks information about the account's encrypted balance to the `delegatee`. + */ +abstract contract Comp is IComp, EncryptedERC20, Ownable2Step { + /// @notice Returned if the `blockNumber` is higher or equal to the (current) `block.number`. + /// @dev It is returned in requests to access votes. + error BlockNumberEqualOrHigherThanCurrentBlock(); + + /// @notice Returned if the `msg.sender` is not the `governor` contract. + error GovernorInvalid(); + + /// @notice Emitted when an `account` (i.e. `delegator`) changes its delegate. + event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); + + /// @notice Emitted when a `delegate` account's vote balance changes. + event DelegateVotesChanged(address indexed delegate); + + /// @notice Emitted when the governor contract that can reencrypt votes changes. + /// @dev WARNING: it can be set to a malicious contract, which could reencrypt all user votes. + event NewGovernor(address indexed governor); + + /// @notice A checkpoint for marking number of votes from a given block. + /// @param fromBlock Block from where the checkpoint applies. + /// @param votes Total number of votes for the account power. + /// @dev In Compound's implementation, `fromBlock` is defined as uint32 to allow tight-packing. + /// However, in this implementations `votes` is uint256-based. + /// `fromBlock`'s type is set to uint256, which simplifies the codebase. + struct Checkpoint { + uint256 fromBlock; + euint64 votes; + } + + /// @notice The EIP-712 typehash for the contract's domain. + bytes32 public constant DOMAIN_TYPEHASH = + keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); + + /// @notice The EIP-712 typehash for the `Delegation` struct. + bytes32 public constant DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + /// @notice The smart contract that can access encrypted votes. + /// @dev The contract is expected to be a governor contract. + address public governor; + + /// @notice A record of each account's `delegate`. + mapping(address account => address delegate) public delegates; + + /// @notice A record of states for signing/validating signatures. + mapping(address account => uint256 nonce) public nonces; + + /// @notice The number of checkpoints for an `account`. + mapping(address account => uint32 _checkpoints) public numCheckpoints; + + /// @notice A record of votes _checkpoints for an `account` using incremental indices. + mapping(address account => mapping(uint32 index => Checkpoint checkpoint)) internal _checkpoints; + + /// @notice Constant for zero using TFHE. + /// @dev Since it is expensive to compute 0, it is stored instead. + /// However, is not possible to define it as constant due to TFHE constraints. + /* solhint-disable var-name-mixedcase*/ + euint64 private _EUINT64_ZERO; + + /** + * @param owner Owner address + */ + constructor(address owner) EncryptedERC20("Compound", "COMP") Ownable(owner) { + _unsafeMint(owner, TFHE.asEuint64(10000000e6)); /// 10 million Comp + _totalSupply = 10000000e6; + + /// @dev Define the constant in the storage. + _EUINT64_ZERO = TFHE.asEuint64(0); + TFHE.allowThis(_EUINT64_ZERO); + } + + /** + * @notice Delegate votes from `msg.sender` to `delegatee`. + * @param delegatee The address to delegate votes to. + */ + function delegate(address delegatee) public virtual { + return _delegate(msg.sender, delegatee); + } + + /** + * @notice Delegate votes from signatory to `delegatee`. + * @param delegatee The address to delegate votes to. + * @param nonce The contract state required to match the signature. + * @param expiry The time at which to expire the signature. + * @param v The recovery byte of the signature. + * @param r Half of the ECDSA signature pair. + * @param s Half of the ECDSA signature pair. + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + bytes32 domainSeparator = keccak256( + abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), block.chainid, address(this)) + ); + bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)); + bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + address signatory = ecrecover(digest, v, r, s); + + require(signatory != address(0), "Comp::delegateBySig: invalid signature"); + require(nonce == nonces[signatory]++, "Comp::delegateBySig: invalid nonce"); + require(block.timestamp <= expiry, "Comp::delegateBySig: signature expired"); + return _delegate(signatory, delegatee); + } + + /** + * @notice See {IComp-getPriorVotesForGovernor}. + */ + function getPriorVotesForGovernor(address account, uint256 blockNumber) public virtual returns (euint64 votes) { + if (msg.sender != governor) { + revert GovernorInvalid(); + } + + if (blockNumber >= block.number) { + revert BlockNumberEqualOrHigherThanCurrentBlock(); + } + + votes = _getPriorVote(account, blockNumber); + TFHE.allow(votes, msg.sender); + } + + /** + * @notice Get current votes of account. + * @param account Account address + * @return votes Current (encrypted) votes. + */ + function getCurrentVotes(address account) public view virtual returns (euint64 votes) { + uint32 nCheckpoints = numCheckpoints[account]; + if (nCheckpoints > 0) { + votes = _checkpoints[account][nCheckpoints - 1].votes; + } + } + + /** + * @notice Get the prior number of votes for an account as of a block number. + * @dev Block number must be a finalized block or else this function will revert. + * @param account Account address. + * @param blockNumber The block number to get the vote balance at. + * @return votes Number of votes the account as of the given block. + */ + function getPriorVotes(address account, uint256 blockNumber) public view virtual returns (euint64 votes) { + if (blockNumber >= block.number) { + revert BlockNumberEqualOrHigherThanCurrentBlock(); + } + + return _getPriorVote(account, blockNumber); + } + + /** + * @notice Set a governor contract. + * @param newGovernor New governor contract that can reencrypt/access votes. + */ + function setGovernor(address newGovernor) public virtual onlyOwner { + governor = newGovernor; + emit NewGovernor(newGovernor); + } + + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates[delegator]; + euint64 delegatorBalance = _balances[delegator]; + TFHE.allowThis(delegatorBalance); + TFHE.allow(delegatorBalance, msg.sender); + delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + _moveDelegates(currentDelegate, delegatee, delegatorBalance); + } + + function _getPriorVote(address account, uint256 blockNumber) internal view returns (euint64 votes) { + uint32 nCheckpoints = numCheckpoints[account]; + + if (nCheckpoints == 0) { + /// If there is no checkpoint for the `account`, return encrypted zero. + /// @dev It will not be possible to reencrypt it by the `account`. + votes = _EUINT64_ZERO; + } else if (_checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { + /// First, check the most recent balance. + votes = _checkpoints[account][nCheckpoints - 1].votes; + } else if (_checkpoints[account][0].fromBlock > blockNumber) { + /// Then, check if there is zero balance. + /// @dev It will not be possible to reencrypt it by the `account`. + votes = _EUINT64_ZERO; + } else { + /// Else, search for the voting power at the `blockNumber`. + uint32 lower = 0; + uint32 upper = nCheckpoints - 1; + while (upper > lower) { + /// Ceil to avoid overflow. + uint32 center = upper - (upper - lower) / 2; + Checkpoint memory cp = _checkpoints[account][center]; + + if (cp.fromBlock == blockNumber) { + return cp.votes; + } else if (cp.fromBlock < blockNumber) { + lower = center; + } else { + upper = center - 1; + } + } + votes = _checkpoints[account][lower].votes; + } + } + + function _moveDelegates(address srcRep, address dstRep, euint64 amount) internal virtual { + if (srcRep != dstRep) { + if (srcRep != address(0)) { + uint32 srcRepNum = numCheckpoints[srcRep]; + euint64 srcRepOld = srcRepNum > 0 ? _checkpoints[srcRep][srcRepNum - 1].votes : _EUINT64_ZERO; + euint64 srcRepNew = TFHE.sub(srcRepOld, amount); /// srcRepOld - amount; + _writeCheckpoint(srcRep, srcRepNum, srcRepNew); + } + + if (dstRep != address(0)) { + uint32 dstRepNum = numCheckpoints[dstRep]; + euint64 dstRepOld = dstRepNum > 0 ? _checkpoints[dstRep][dstRepNum - 1].votes : _EUINT64_ZERO; + euint64 dstRepNew = TFHE.add(dstRepOld, amount); /// dstRepOld + amount; + _writeCheckpoint(dstRep, dstRepNum, dstRepNew); + } + } + } + + /// @dev Original restrictions to transfer from/to address(0) are removed since they + /// are inherited. + function _transfer(address from, address to, euint64 amount, ebool isTransferable) internal virtual override { + super._transfer(from, to, amount, isTransferable); + _moveDelegates(delegates[from], delegates[to], amount); + } + + function _writeCheckpoint(address delegatee, uint32 nCheckpoints, euint64 newVotes) internal virtual { + if (nCheckpoints > 0 && _checkpoints[delegatee][nCheckpoints - 1].fromBlock == block.number) { + _checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; + } else { + _checkpoints[delegatee][nCheckpoints] = Checkpoint(block.number, newVotes); + numCheckpoints[delegatee] = nCheckpoints + 1; + } + + TFHE.allowThis(newVotes); + TFHE.allow(newVotes, delegatee); + emit DelegateVotesChanged(delegatee); + } +} diff --git a/contracts/DAO/Timelock.sol b/contracts/governance/CompoundTimelock.sol similarity index 64% rename from contracts/DAO/Timelock.sol rename to contracts/governance/CompoundTimelock.sol index c4cac1e..b716fdd 100644 --- a/contracts/DAO/Timelock.sol +++ b/contracts/governance/CompoundTimelock.sol @@ -1,45 +1,47 @@ // SPDX-License-Identifier: BSD-3-Clause -pragma solidity ^0.8.20; - -contract Timelock { - event NewAdmin(address indexed newAdmin); - event NewPendingAdmin(address indexed newPendingAdmin); - event NewDelay(uint256 indexed newDelay); - event CancelTransaction( - bytes32 indexed txHash, - address indexed target, - uint256 value, - string signature, - bytes data, - uint256 eta - ); - event ExecuteTransaction( - bytes32 indexed txHash, - address indexed target, - uint256 value, - string signature, - bytes data, - uint256 eta - ); - event QueueTransaction( - bytes32 indexed txHash, - address indexed target, - uint256 value, - string signature, - bytes data, - uint256 eta - ); - +pragma solidity ^0.8.24; + +import { ICompoundTimelock } from "./ICompoundTimelock.sol"; + +/** + * @title CompoundTimelock + * @notice This contract allows the admin to set a delay period before executing transactions. + * Transactions must be queued before execution. No transaction can be executed during this period, + * which offers time to verify the validity of pending transactions. + * It also has a grace period to allow for transactions + * not to be executed after a specific period following the queuing. + */ +contract CompoundTimelock is ICompoundTimelock { + /** + * @notice See {ICompoundTimelock-GRACE_PERIOD}. + */ uint256 public constant GRACE_PERIOD = 14 days; + + /// @notice Minimum delay that can be set in the setDelay function. uint256 public constant MINIMUM_DELAY = 2 days; + + /// @notice Maximum delay that can be set in the setDelay function. uint256 public constant MAXIMUM_DELAY = 30 days; + /// @notice Admin address. address public admin; + + /// @notice Pending admin address. + /// @dev The transer of the admin is a two-step process. address public pendingAdmin; + + /** + * @notice See {ICompoundTimelock-delay}. + */ uint256 public delay; + /// @notice Return whether the transaction is queued based on its hash. mapping(bytes32 => bool) public queuedTransactions; + /** + * @param admin_ Admin address. + * @param delay_ Delay (in timestamp). + */ constructor(address admin_, uint256 delay_) { require(delay_ >= MINIMUM_DELAY, "Timelock::constructor: Delay must exceed minimum delay."); require(delay_ <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay."); @@ -50,6 +52,11 @@ contract Timelock { receive() external payable {} + /** + * @notice Set the delay. + * @dev This transaction must be queued. + * @param delay_ Delay (in timestamp). + */ function setDelay(uint256 delay_) public { require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock."); require(delay_ >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay."); @@ -59,6 +66,9 @@ contract Timelock { emit NewDelay(delay); } + /** + * @notice See {ICompoundTimelock-acceptAdmin}. + */ function acceptAdmin() public { require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin."); admin = msg.sender; @@ -67,6 +77,11 @@ contract Timelock { emit NewAdmin(admin); } + /** + * @notice Set the pending admin. + * @dev This transaction must be queued. + * @param pendingAdmin_ Pending admin address. + */ function setPendingAdmin(address pendingAdmin_) public { require(msg.sender == address(this), "Timelock::setPendingAdmin: Call must come from Timelock."); pendingAdmin = pendingAdmin_; @@ -74,6 +89,9 @@ contract Timelock { emit NewPendingAdmin(pendingAdmin); } + /** + * @notice See {ICompoundTimelock-queueTransaction}. + */ function queueTransaction( address target, uint256 value, @@ -83,7 +101,7 @@ contract Timelock { ) public returns (bytes32) { require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin."); require( - eta >= getBlockTimestamp() + delay, + eta >= block.timestamp + delay, "Timelock::queueTransaction: Estimated execution block must satisfy delay." ); @@ -94,6 +112,9 @@ contract Timelock { return txHash; } + /** + * @notice See {ICompoundTimelock-cancelTransaction}. + */ function cancelTransaction( address target, uint256 value, @@ -109,6 +130,9 @@ contract Timelock { emit CancelTransaction(txHash, target, value, signature, data, eta); } + /** + * @notice See {ICompoundTimelock-executeTransaction}. + */ function executeTransaction( address target, uint256 value, @@ -120,8 +144,8 @@ contract Timelock { bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued."); - require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock."); - require(getBlockTimestamp() <= eta + GRACE_PERIOD, "Timelock::executeTransaction: Transaction is stale."); + require(block.timestamp >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock."); + require(block.timestamp <= eta + GRACE_PERIOD, "Timelock::executeTransaction: Transaction is stale."); queuedTransactions[txHash] = false; @@ -140,8 +164,4 @@ contract Timelock { return returnData; } - - function getBlockTimestamp() internal view returns (uint256) { - return block.timestamp; - } } diff --git a/contracts/governance/GovernorAlphaZama.sol b/contracts/governance/GovernorAlphaZama.sol new file mode 100644 index 0000000..74ec0e5 --- /dev/null +++ b/contracts/governance/GovernorAlphaZama.sol @@ -0,0 +1,680 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/gateway/GatewayCaller.sol"; + +import { Ownable2Step, Ownable } from "@openzeppelin/contracts/access/Ownable2Step.sol"; +import { IComp } from "./IComp.sol"; +import { ICompoundTimelock } from "./ICompoundTimelock.sol"; + +/** + * @title GovernorAlphaZama + * @notice This is based on the GovernorAlpha.sol contract written by Compound Labs. + * see: compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol + * This decentralized governance system allows users to propose and vote on changes to the protocol. + * The contract is responsible for: + * - Proposal: A new proposal is made to introduce a change. + * - Voting: Users can vote on the proposal, either in favor or against it. + * - Quorum: A minimum number of votes (quorum) must be reached for the proposal to pass. + * - Execution: Once a proposal passes, it is executed and takes effect on the protocol. + */ +abstract contract GovernorAlphaZama is Ownable2Step, GatewayCaller { + /// @notice Returned if proposal contains too many changes. + error LengthAboveMaxOperations(); + + /// @notice Returned if the array length is equal to 0. + error LengthIsNull(); + + /// @notice Returned if array lengths are not equal. + error LengthsDoNotMatch(); + + /// @notice Returned if proposal's actions have already been queued. + error ProposalActionsAlreadyQueued(); + + /// @notice Returned if the proposal state is invalid for this operation. + /// @dev It is returned for any proposal state not matching the expected + /// state to conduct the operation. + error ProposalStateInvalid(); + + /// @notice Returned if the proposal's state is active but `block.number` > `endBlock`. + error ProposalStateNotActive(); + + /// @notice Returned if the proposal state is still active. + error ProposalStateStillActive(); + + /// @notice Returned if the proposer has another proposal in progress. + error ProposerHasAnotherProposal(); + + /// @notice Returned if the voter has already cast a vote + /// for this proposal. + error VoterHasAlreadyVoted(); + + /// @notice Emitted when a proposal is now active. + event ProposalActive(uint256 id); + + /// @notice Emitted when a proposal has been canceled. + event ProposalCanceled(uint256 id); + + /// @notice Emitted when a new proposal is created. + event ProposalCreated( + uint256 id, + address proposer, + address[] targets, + uint256[] values, + string[] signatures, + bytes[] calldatas, + uint256 startBlock, + uint256 endBlock, + string description + ); + + /// @notice Emitted when a proposal is defeated either by lack of votes or by + /// more votes against. + event ProposalDefeated(uint256 id); + + /// @notice Emitted when a proposal has been executed in the Timelock. + event ProposalExecuted(uint256 id); + + /// @notice Emitted when a proposal has been queued in the Timelock. + event ProposalQueued(uint256 id, uint256 eta); + + /// @notice Emitted when a proposal has been rejected since the number of votes is lower + /// than the required threshold. + event ProposalRejected(uint256 id); + + /// @notice Emitted when a proposal has been rejected since the number of votes is lower + /// than the required threshold. + event ProposalSucceeded(uint256 id); + + /// @notice Emitted when a vote has been cast on a proposal. + event VoteCast(address voter, uint256 proposalId); + + /** + * @notice Possible states that a proposal may be in. + * @param Pending Proposal does not exist. + * @param PendingThresholdVerification Proposal is created but token threshold verification is pending. + * @param Rejected Proposal was rejected as the proposer did not meet the token threshold. + * @param Active Proposal is active and voters can cast their votes. + * @param PendingResults Proposal is not active and the result decryption is in progress. + * @param Canceled Proposal has been canceled by the proposer or by this contract's owner. + * @param Defeated Proposal has been defeated + * (either not reaching the quorum or `againstVotes` > `forVotes`). + * @param Succeeded Proposal has succeeded (`forVotes` > `againstVotes`). + * @param Queued Proposal has been queued in the `Timelock`. + * @param Expired Proposal has expired (@dev This state exists only in read-only functions). + * @param Executed Proposal has been executed in the `Timelock`. + */ + enum ProposalState { + Pending, + PendingThresholdVerification, + Rejected, + Active, + PendingResults, + Canceled, + Defeated, + Succeeded, + Queued, + Expired, + Executed + } + + /** + * @param proposer Proposal creator. + * @param eta The timestamp that the proposal will be available for execution, + * it is set automatically once the vote succeeds. + * @param targets The ordered list of target addresses for calls to be made. + * @param values The ordered list of values (i.e. `msg.value`) to be passed to the calls to be made. + * @param signatures The ordered list of function signatures to be called. + * @param calldatas The ordered list of calldata to be passed to each call. + * @param startBlock The block at which voting begins: holders must delegate their votes prior + * to this block. + * @param endBlock The block at which voting ends: votes must be cast prior to this block. + * @param forVotes Current encrypted number of votes for to this proposal. + * @param againstVotes Current encrypted number of votes in opposition to this proposal. + * @param forVotesDecrypted For votes once decrypted by the gateway. + * @param againstVotesDecrypted Against votes once decrypted by the gateway. + */ + + struct Proposal { + address proposer; + ProposalState state; + uint256 eta; + address[] targets; + uint256[] values; + string[] signatures; + bytes[] calldatas; + uint256 startBlock; + uint256 endBlock; + euint64 forVotes; + euint64 againstVotes; + uint64 forVotesDecrypted; + uint64 againstVotesDecrypted; + } + + /** + * @param proposer Proposal creator. + * @param state State of the proposal. + * @param eta The timestamp when the proposal will be available for execution, set once the vote succeeds. + * @param targets The ordered list of target addresses for calls to be made. + * @param values The ordered list of values (i.e. `msg.value`) to be passed to the calls to be made. + * @param signatures The ordered list of function signatures to be called. + * @param calldatas The ordered list of calldata to be passed to each call. + * @param startBlock The block at which voting begins: holders must delegate their votes prior to this block. + * @param endBlock The block at which voting ends: votes must be cast prior to this block. + * @param forVotes Number of votes for this proposal once decrypted. + * @param againstVotes Number of votes in opposition to this proposal once decrypted. + */ + struct ProposalInfo { + address proposer; + ProposalState state; + uint256 eta; + address[] targets; + uint256[] values; + string[] signatures; + bytes[] calldatas; + uint256 startBlock; + uint256 endBlock; + uint64 forVotes; + uint64 againstVotes; + } + + /** + * @notice Ballot receipt record for a voter. + * @param hasVoted Whether or not a vote has been cast. + * @param support Whether or not the voter supports the proposal. + * @param votes The number of votes cast by the voter. + */ + struct Receipt { + bool hasVoted; + ebool support; + euint64 votes; + } + + /// @notice The maximum number of actions that can be included in a proposal. + /// @dev It is 10 actions per proposal. + uint256 public constant PROPOSAL_MAX_OPERATIONS = 10; + + /// @notice The number of votes required for a voter to become a proposer. + /// @dev It is set at 100,000, which is 1% of the total supply of the Comp token. + uint256 public constant PROPOSAL_THRESHOLD = 100000e6; + + /// @notice The number of votes in support of a proposal required in order for a quorum to be reached + /// and for a vote to succeed. + /// @dev It is set at 400,000, which is 4% of the total supply of the Comp token. + uint64 public constant QUORUM_VOTES = 400000e6; + + /// @notice The delay before voting on a proposal may take place once proposed. + /// It is 1 block. + uint256 public constant VOTING_DELAY = 1; + + /// @notice The duration of voting on a proposal, in blocks + /// @dev It is recommended to be set at 3 days in blocks + /// (i.e 21,600 for 12-second blocks). + uint256 public immutable VOTING_PERIOD; + + /// @notice Comp governance token. + IComp public immutable COMP; + + /// @notice Compound Timelock. + ICompoundTimelock public immutable TIMELOCK; + + /// @notice Constant for zero using TFHE. + /// @dev Since it is expensive to compute 0, it is stored instead. + /// However, is not possible to define it as constant due to TFHE constraints. + /* solhint-disable var-name-mixedcase*/ + euint64 private _EUINT64_ZERO; + + /// @notice Constant for PROPOSAL_THRESHOLD using TFHE. + /// @dev Since it is expensive to compute 0, it is stored instead. + /// However, is not possible to define it as constant due to TFHE constraints. + /* solhint-disable var-name-mixedcase*/ + euint64 private _EUINT64_PROPOSAL_THRESHOLD; + + /// @notice The total number of proposals made. + /// It includes all proposals, including the ones that + /// were rejected/canceled/defeated. + uint256 public proposalCount; + + /// @notice The latest proposal for each proposer. + mapping(address proposer => uint256 proposalId) public latestProposalIds; + + /// @notice Ballot receipt for an account for a proposal id. + mapping(uint256 proposalId => mapping(address => Receipt)) internal _accountReceiptForProposalId; + + /// @notice The official record of all proposals that have been created. + mapping(uint256 proposalId => Proposal proposal) internal _proposals; + + /// @notice Returns the proposal id associated with the request id from the Gateway. + /// @dev This mapping is used for decryption. + mapping(uint256 requestId => uint256 proposalId) internal _requestIdToProposalId; + + /** + * @param owner_ Owner address. + * @param timelock_ Timelock contract. + * @param comp_ Comp token. + * @param votingPeriod_ Voting period. + * @dev Do not use a small value in production such as 5 or 20 to avoid security issues + * unless for testing purpose. It should by at least a few days,. + * For instance, 3 days would have a votingPeriod = 21,600 blocks if 12s per block. + */ + constructor(address owner_, address timelock_, address comp_, uint256 votingPeriod_) Ownable(owner_) { + TIMELOCK = ICompoundTimelock(timelock_); + COMP = IComp(comp_); + VOTING_PERIOD = votingPeriod_; + + /// @dev Store these constant-like variables in the storage. + _EUINT64_ZERO = TFHE.asEuint64(0); + _EUINT64_PROPOSAL_THRESHOLD = TFHE.asEuint64(PROPOSAL_THRESHOLD); + + TFHE.allowThis(_EUINT64_ZERO); + TFHE.allowThis(_EUINT64_PROPOSAL_THRESHOLD); + } + + /** + * @notice Cancel the proposal. + * @param proposalId Proposal id. + * @dev Only this contract's owner or the proposer can cancel. + * In the original GovernorAlpha, the proposer can cancel only if + * her votes are still above the threshold. + */ + function cancel(uint256 proposalId) public virtual { + Proposal memory proposal = _proposals[proposalId]; + + if ( + proposal.state == ProposalState.Rejected || + proposal.state == ProposalState.Canceled || + proposal.state == ProposalState.Defeated || + proposal.state == ProposalState.Executed + ) { + revert ProposalStateInvalid(); + } + + if (msg.sender != proposal.proposer) { + _checkOwner(); + } + + /// @dev It is not necessary to cancel the transaction in the timelock + /// unless the proposal has been queued. + if (proposal.state == ProposalState.Queued) { + for (uint256 i = 0; i < proposal.targets.length; i++) { + TIMELOCK.cancelTransaction( + proposal.targets[i], + proposal.values[i], + proposal.signatures[i], + proposal.calldatas[i], + proposal.eta + ); + } + } + + _proposals[proposalId].state = ProposalState.Canceled; + + emit ProposalCanceled(proposalId); + } + + /** + * @notice Cast a vote. + * @param proposalId Proposal id. + * @param value Encrypted value. + * @param inputProof Input proof. + */ + function castVote(uint256 proposalId, einput value, bytes calldata inputProof) public virtual { + return castVote(proposalId, TFHE.asEbool(value, inputProof)); + } + + /** + * @notice Cast a vote. + * @param proposalId Proposal id. + * @param support Support (true ==> `forVotes`, false ==> `againstVotes`) + */ + function castVote(uint256 proposalId, ebool support) public virtual { + return _castVote(msg.sender, proposalId, support); + } + + /** + * @notice Execute the proposal id. + * @dev Anyone can execute a proposal once it has been queued and the + * delay in the timelock is sufficient. + */ + function execute(uint256 proposalId) public payable virtual { + Proposal memory proposal = _proposals[proposalId]; + + if (proposal.state != ProposalState.Queued) { + revert ProposalStateInvalid(); + } + + for (uint256 i = 0; i < proposal.targets.length; i++) { + TIMELOCK.executeTransaction{ value: proposal.values[i] }( + proposal.targets[i], + proposal.values[i], + proposal.signatures[i], + proposal.calldatas[i], + proposal.eta + ); + } + + _proposals[proposalId].state = ProposalState.Executed; + + emit ProposalExecuted(proposalId); + } + + /** + * @notice Start a new proposal. + * @param targets Target addresses. + * @param values Values. + * @param signatures Signatures. + * @param calldatas Calldatas. + * @param description Plain text description of the proposal. + * @return proposalId Proposal id. + */ + function propose( + address[] memory targets, + uint256[] memory values, + string[] memory signatures, + bytes[] memory calldatas, + string memory description + ) public virtual returns (uint256 proposalId) { + { + uint256 length = targets.length; + + if (length != values.length || length != signatures.length || length != calldatas.length) { + revert LengthsDoNotMatch(); + } + + if (length == 0) { + revert LengthIsNull(); + } + + if (length > PROPOSAL_MAX_OPERATIONS) { + revert LengthAboveMaxOperations(); + } + } + + uint256 latestProposalId = latestProposalIds[msg.sender]; + + if (latestProposalId != 0) { + ProposalState proposerLatestProposalState = _proposals[latestProposalId].state; + + if ( + proposerLatestProposalState != ProposalState.Rejected && + proposerLatestProposalState != ProposalState.Defeated && + proposerLatestProposalState != ProposalState.Canceled && + proposerLatestProposalState != ProposalState.Executed + ) { + revert ProposerHasAnotherProposal(); + } + } + + uint256 startBlock = block.number + VOTING_DELAY; + uint256 endBlock = startBlock + VOTING_PERIOD; + uint256 thisProposalId = ++proposalCount; + + _proposals[thisProposalId] = Proposal({ + proposer: msg.sender, + state: ProposalState.PendingThresholdVerification, + eta: 0, + targets: targets, + values: values, + signatures: signatures, + calldatas: calldatas, + startBlock: startBlock, + endBlock: endBlock, + forVotes: _EUINT64_ZERO, + againstVotes: _EUINT64_ZERO, + forVotesDecrypted: 0, + againstVotesDecrypted: 0 + }); + + latestProposalIds[msg.sender] = thisProposalId; + + emit ProposalCreated( + thisProposalId, + msg.sender, + targets, + values, + signatures, + calldatas, + startBlock, + endBlock, + description + ); + + ebool canPropose = TFHE.lt( + _EUINT64_PROPOSAL_THRESHOLD, + COMP.getPriorVotesForGovernor(msg.sender, block.number - 1) + ); + + uint256[] memory cts = new uint256[](1); + cts[0] = Gateway.toUint256(canPropose); + + uint256 requestId = Gateway.requestDecryption( + cts, + this.callbackInitiateProposal.selector, + 0, + block.timestamp + 100, + false + ); + + _requestIdToProposalId[requestId] = thisProposalId; + + return thisProposalId; + } + + /** + * @notice Queue a new proposal. + * @dev It can be done only if the proposal has succeeded. + * Anyone can queue a proposal. + * @param proposalId Proposal id. + */ + function queue(uint256 proposalId) public virtual { + Proposal memory proposal = _proposals[proposalId]; + + if (proposal.state != ProposalState.Succeeded) { + revert ProposalStateInvalid(); + } + + uint256 eta = block.timestamp + TIMELOCK.delay(); + + for (uint256 i = 0; i < proposal.targets.length; i++) { + _queueOrRevert(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], eta); + } + + _proposals[proposalId].eta = eta; + _proposals[proposalId].state = ProposalState.Queued; + + emit ProposalQueued(proposalId, eta); + } + + /** + * @notice Request the vote results to be decrypted. + * @dev Anyone can request the decryption of the vote. + * @param proposalId Proposal id. + */ + function requestVoteDecryption(uint256 proposalId) public virtual { + if (_proposals[proposalId].state != ProposalState.Active) { + revert ProposalStateInvalid(); + } + + if (_proposals[proposalId].endBlock >= block.number) { + revert ProposalStateStillActive(); + } + + uint256[] memory cts = new uint256[](2); + cts[0] = Gateway.toUint256(_proposals[proposalId].forVotes); + cts[1] = Gateway.toUint256(_proposals[proposalId].againstVotes); + + uint256 requestId = Gateway.requestDecryption( + cts, + this.callbackVoteDecryption.selector, + 0, + block.timestamp + 100, + false + ); + + _requestIdToProposalId[requestId] = proposalId; + _proposals[proposalId].state = ProposalState.PendingResults; + } + + /** + * @dev Only callable by the gateway. + * @param requestId Request id (from the Gateway) + * @param canInitiate Whether the proposal can be initiated. + */ + function callbackInitiateProposal(uint256 requestId, bool canInitiate) public virtual onlyGateway { + uint256 proposalId = _requestIdToProposalId[requestId]; + + if (canInitiate) { + _proposals[proposalId].state = ProposalState.Active; + emit ProposalActive(proposalId); + } else { + _proposals[proposalId].state = ProposalState.Rejected; + emit ProposalRejected(proposalId); + } + } + + /** + * @dev Only callable by the gateway. + * If `forVotesDecrypted` == `againstVotesDecrypted`, proposal is defeated. + * @param forVotesDecrypted For votes. + * @param againstVotesDecrypted Against votes. + */ + function callbackVoteDecryption( + uint256 requestId, + uint256 forVotesDecrypted, + uint256 againstVotesDecrypted + ) public virtual onlyGateway { + uint256 proposalId = _requestIdToProposalId[requestId]; + + /// @dev It is safe to downcast since the original values were euint64. + _proposals[proposalId].forVotesDecrypted = uint64(forVotesDecrypted); + _proposals[proposalId].againstVotesDecrypted = uint64(againstVotesDecrypted); + + if (forVotesDecrypted > againstVotesDecrypted && forVotesDecrypted >= QUORUM_VOTES) { + _proposals[proposalId].state = ProposalState.Succeeded; + emit ProposalSucceeded(proposalId); + } else { + _proposals[proposalId].state = ProposalState.Defeated; + emit ProposalDefeated(proposalId); + } + } + + /** + * @dev Only callable by `owner`. + */ + function acceptTimelockAdmin() public virtual onlyOwner { + TIMELOCK.acceptAdmin(); + } + + /** + * @dev Only callable by `owner`. + * @param newPendingAdmin Address of the new pending admin for the timelock. + * @param eta Eta for executing the transaction in the timelock. + */ + function executeSetTimelockPendingAdmin(address newPendingAdmin, uint256 eta) public virtual onlyOwner { + TIMELOCK.executeTransaction(address(TIMELOCK), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); + } + + /** + * @dev Only callable by `owner`. + * @param newPendingAdmin Address of the new pending admin for the timelock. + * @param eta Eta for queuing the transaction in the timelock. + */ + function queueSetTimelockPendingAdmin(address newPendingAdmin, uint256 eta) public virtual onlyOwner { + TIMELOCK.queueTransaction(address(TIMELOCK), 0, "setPendingAdmin(address)", abi.encode(newPendingAdmin), eta); + } + + /** + * @notice Returns proposal information for a proposal id. + * @dev It returns decrypted `forVotes`/`againstVotes`. + * These are only available after the decryption. + * @param proposalId Proposal id. + * @return proposalInfo Proposal information. + */ + function getProposalInfo(uint256 proposalId) public view virtual returns (ProposalInfo memory proposalInfo) { + Proposal memory proposal = _proposals[proposalId]; + proposalInfo.proposer = proposal.proposer; + proposalInfo.state = proposal.state; + proposalInfo.eta = proposal.eta; + proposalInfo.targets = proposal.targets; + proposalInfo.values = proposal.values; + proposalInfo.signatures = proposal.signatures; + proposalInfo.calldatas = proposal.calldatas; + proposalInfo.startBlock = proposal.startBlock; + proposalInfo.endBlock = proposal.endBlock; + proposalInfo.forVotes = proposal.forVotesDecrypted; + proposalInfo.againstVotes = proposal.againstVotesDecrypted; + + /// The state is adjusted but not closed. + if ( + (proposalInfo.state == ProposalState.Queued) && + (block.timestamp > proposalInfo.eta + TIMELOCK.GRACE_PERIOD()) + ) { + proposalInfo.state = ProposalState.Expired; + } + } + + /** + * @notice Returns the vote receipt information for the account for a proposal id. + * @param proposalId Proposal id. + * @param account Account address. + * @return hasVoted Whether the account has voted. + * @return support The support for the account (true ==> vote for, false ==> vote against). + * @return votes The number of votes cast. + */ + function getReceipt(uint256 proposalId, address account) public view virtual returns (bool, ebool, euint64) { + Receipt memory receipt = _accountReceiptForProposalId[proposalId][account]; + return (receipt.hasVoted, receipt.support, receipt.votes); + } + + function _castVote(address voter, uint256 proposalId, ebool support) internal virtual { + Proposal storage proposal = _proposals[proposalId]; + + if (proposal.state != ProposalState.Active) { + revert ProposalStateInvalid(); + } + + if (block.number > proposal.endBlock) { + revert ProposalStateNotActive(); + } + + Receipt storage receipt = _accountReceiptForProposalId[proposalId][voter]; + + if (receipt.hasVoted) { + revert VoterHasAlreadyVoted(); + } + + euint64 votes = COMP.getPriorVotesForGovernor(voter, proposal.startBlock); + proposal.forVotes = TFHE.select(support, TFHE.add(proposal.forVotes, votes), proposal.forVotes); + proposal.againstVotes = TFHE.select(support, proposal.againstVotes, TFHE.add(proposal.againstVotes, votes)); + + receipt.hasVoted = true; + receipt.support = support; + receipt.votes = votes; + + TFHE.allowThis(proposal.forVotes); + TFHE.allowThis(proposal.againstVotes); + TFHE.allowThis(receipt.support); + TFHE.allowThis(receipt.votes); + TFHE.allow(receipt.support, msg.sender); + TFHE.allow(receipt.votes, msg.sender); + + /// @dev `support` and `votes` are encrypted values. + /// There is no need to include them in the event. + emit VoteCast(voter, proposalId); + } + + function _queueOrRevert( + address target, + uint256 value, + string memory signature, + bytes memory data, + uint256 eta + ) internal virtual { + if (TIMELOCK.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta)))) { + revert ProposalActionsAlreadyQueued(); + } + + TIMELOCK.queueTransaction(target, value, signature, data, eta); + } +} diff --git a/contracts/governance/IComp.sol b/contracts/governance/IComp.sol new file mode 100644 index 0000000..a93e0a7 --- /dev/null +++ b/contracts/governance/IComp.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; + +/** + * @title IComp + * @dev The GovernorAlphaZama relies on this interface. + */ +interface IComp { + /** + * @notice Determine the prior number of votes for an account as of a block number. + * @dev Block number must be a finalized block or else this function will revert. + * This function can change the state since the governor needs access in the ACL + * contract. + * @param account Account address. + * @param blockNumber The block number to get the vote balance at. + * @return votes Number of votes the account as of the given block number. + */ + function getPriorVotesForGovernor(address account, uint256 blockNumber) external returns (euint64 votes); +} diff --git a/contracts/governance/ICompoundTimelock.sol b/contracts/governance/ICompoundTimelock.sol new file mode 100644 index 0000000..ff3bb3f --- /dev/null +++ b/contracts/governance/ICompoundTimelock.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.24; + +/** + * @title ICompoundTimelock + */ +interface ICompoundTimelock { + /// @notice Emitted when there is a change of admin. + event NewAdmin(address indexed newAdmin); + + /// @notice Emtited when there is a change of pending admin. + event NewPendingAdmin(address indexed newPendingAdmin); + + /// @notice Emitted when there is a new delay set. + event NewDelay(uint256 indexed newDelay); + + /// @notice Emitted when the queued transaction is canceled. + event CancelTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + + /// @notice Emitted when the queued transaction is executed. + event ExecuteTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + + /// @notice Emitted when a transaction is queued. + event QueueTransaction( + bytes32 indexed txHash, + address indexed target, + uint256 value, + string signature, + bytes data, + uint256 eta + ); + + /** + * @notice Returns the delay (in timestamp) for a queued transaction before it can be executed. + */ + function delay() external view returns (uint256); + + /** + * @notice Returns the grace period (in timestamp). + * The grace period indicates how long a transaction can remain queued before it cannot be + * executed again. + */ + function GRACE_PERIOD() external view returns (uint256); + + /** + * @notice Accept admin role. + */ + function acceptAdmin() external; + + /** + * @notice Returns whether the transactions are queued. + */ + function queuedTransactions(bytes32 hash) external view returns (bool); + + /** + * @notice Queue a transaction. + * @param target Target address to execute the transaction. + * @param signature Function signature to execute. + * @param data The data to include in the transaction. + * @param eta The earliest eta to queue the transaction. + * @return hashTransaction The transaction's hash. + */ + function queueTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external returns (bytes32 hashTransaction); + + /** + * @notice Cancel a queued transaction. + * @param target Target address to execute the transaction. + * @param signature Function signature to execute. + * @param data The data to include in the transaction. + * @param eta The earliest eta to queue the transaction. + */ + function cancelTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external; + + /** + * @notice Cancel a queued transaction. + * @param target Target address to execute the transaction. + * @param signature Function signature to execute. + * @param data The data to include in the transaction. + * @param eta The earliest eta to queue the transaction. + * @return response The response from the transaction once executed. + */ + function executeTransaction( + address target, + uint256 value, + string calldata signature, + bytes calldata data, + uint256 eta + ) external payable returns (bytes memory response); +} diff --git a/contracts/test/DefaultFHEVMConfig.sol b/contracts/test/DefaultFHEVMConfig.sol new file mode 100644 index 0000000..07dc36a --- /dev/null +++ b/contracts/test/DefaultFHEVMConfig.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; + +contract DefaultFHEVMConfig { + constructor() { + TFHE.setFHEVM(FHEVMConfig.defaultConfig()); + } +} diff --git a/contracts/test/DefaultGatewayConfig.sol b/contracts/test/DefaultGatewayConfig.sol new file mode 100644 index 0000000..75c87d1 --- /dev/null +++ b/contracts/test/DefaultGatewayConfig.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import "fhevm/gateway/GatewayCaller.sol"; + +contract DefaultGatewayConfig { + constructor() { + Gateway.setGateway(Gateway.defaultGatewayAddress()); + } +} diff --git a/contracts/test/governance/TestComp.sol b/contracts/test/governance/TestComp.sol new file mode 100644 index 0000000..a4c4f11 --- /dev/null +++ b/contracts/test/governance/TestComp.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import { Comp } from "../../governance/Comp.sol"; +import { DefaultFHEVMConfig } from "../DefaultFHEVMConfig.sol"; + +contract TestComp is DefaultFHEVMConfig, Comp { + constructor(address owner_) Comp(owner_) { + // + } +} diff --git a/contracts/test/governance/TestGovernorAlphaZama.sol b/contracts/test/governance/TestGovernorAlphaZama.sol new file mode 100644 index 0000000..724ac71 --- /dev/null +++ b/contracts/test/governance/TestGovernorAlphaZama.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import { GovernorAlphaZama } from "../../governance/GovernorAlphaZama.sol"; +import { DefaultFHEVMConfig } from "../DefaultFHEVMConfig.sol"; +import { DefaultGatewayConfig } from "../DefaultGatewayConfig.sol"; + +contract TestGovernorAlphaZama is DefaultFHEVMConfig, DefaultGatewayConfig, GovernorAlphaZama { + constructor( + address owner_, + address timelock_, + address comp_, + uint256 votingPeriod_ + ) GovernorAlphaZama(owner_, timelock_, comp_, votingPeriod_) { + // + } +} diff --git a/contracts/test/token/ERC20/TestEncryptedERC20Mintable.sol b/contracts/test/token/ERC20/TestEncryptedERC20Mintable.sol new file mode 100644 index 0000000..2f0968b --- /dev/null +++ b/contracts/test/token/ERC20/TestEncryptedERC20Mintable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import { EncryptedERC20Mintable } from "../../../token/ERC20/extensions/EncryptedERC20Mintable.sol"; +import { DefaultFHEVMConfig } from "../../DefaultFHEVMConfig.sol"; + +contract TestEncryptedERC20Mintable is DefaultFHEVMConfig, EncryptedERC20Mintable { + constructor( + string memory name_, + string memory symbol_, + address owner_ + ) EncryptedERC20Mintable(name_, symbol_, owner_) { + // + } +} diff --git a/contracts/test/token/ERC20/TestEncryptedERC20WithErrorsMintable.sol b/contracts/test/token/ERC20/TestEncryptedERC20WithErrorsMintable.sol new file mode 100644 index 0000000..e415a20 --- /dev/null +++ b/contracts/test/token/ERC20/TestEncryptedERC20WithErrorsMintable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import { EncryptedERC20WithErrorsMintable } from "../../../token/ERC20/extensions/EncryptedERC20WithErrorsMintable.sol"; +import { DefaultFHEVMConfig } from "../../DefaultFHEVMConfig.sol"; + +contract TestEncryptedERC20WithErrorsMintable is DefaultFHEVMConfig, EncryptedERC20WithErrorsMintable { + constructor( + string memory name_, + string memory symbol_, + address owner_ + ) EncryptedERC20WithErrorsMintable(name_, symbol_, owner_) { + // + } +} diff --git a/contracts/token/ERC20/EncryptedERC20.sol b/contracts/token/ERC20/EncryptedERC20.sol index 6ce1b13..cf6689b 100644 --- a/contracts/token/ERC20/EncryptedERC20.sol +++ b/contracts/token/ERC20/EncryptedERC20.sol @@ -1,201 +1,214 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.20; +pragma solidity ^0.8.24; import "fhevm/lib/TFHE.sol"; -import "fhevm/abstracts/Reencrypt.sol"; -import "../../utils/EncryptedErrors.sol"; - -abstract contract EncryptedERC20 is Reencrypt, EncryptedErrors { - enum ErrorCodes { - NO_ERROR, - UNSUFFICIENT_BALANCE, - UNSUFFICIENT_APPROVAL - } - - struct AllowedErrorReencryption { - address spender; // account's address allowed to reencrypt errorCode - euint8 errorCode; - } +import { IEncryptedERC20 } from "./IEncryptedERC20.sol"; + +/** + * @title EncryptedERC20 + * @notice This contract implements an encrypted ERC20-like token with confidential balances using + * Zama's FHE (Fully Homomorphic Encryption) library. + * @dev It supports standard ERC20 functions such as transferring tokens, minting, + * and setting allowances, but uses encrypted data types. + * The total supply is not encrypted. + */ +abstract contract EncryptedERC20 is IEncryptedERC20 { + /// @notice Total supply. + uint64 internal _totalSupply; - event Transfer(uint256 indexed transferId, address indexed from, address indexed to); - event Approval(address indexed owner, address indexed spender); - event Mint(address indexed to, uint64 amount); + /// @notice Name. + string internal _name; - uint64 internal _totalSupply; - string private _name; - string private _symbol; - uint8 public constant decimals = 6; + /// @notice Symbol. + string internal _symbol; - // A mapping from transferId to the AllowedErrorReencryption. - mapping(uint256 => AllowedErrorReencryption) internal allowedErrorReencryptions; + /// @notice A mapping from `account` address to an encrypted `balance`. + mapping(address account => euint64 balance) internal _balances; - // A mapping from address to an encrypted balance. - mapping(address => euint64) internal balances; + /// @notice A mapping of the form mapping(account => mapping(spender => allowance)). + mapping(address account => mapping(address spender => euint64 allowance)) internal _allowances; - // A mapping of the form mapping(owner => mapping(spender => allowance)). - mapping(address => mapping(address => euint64)) internal allowances; + /** + * @notice Error when the `sender` is not allowed to access a value. + */ + error TFHESenderNotAllowed(); - constructor(string memory name_, string memory symbol_) EncryptedErrors(uint8(type(ErrorCodes).max)) { + /** + * @param name_ Name of the token. + * @param symbol_ Symbol. + */ + constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } - // Returns the name of the token. - function name() public view virtual returns (string memory) { - return _name; + /** + * @notice See {IEncryptedERC20-approve}. + */ + function approve(address spender, einput encryptedAmount, bytes calldata inputProof) public virtual returns (bool) { + approve(spender, TFHE.asEuint64(encryptedAmount, inputProof)); + return true; } - // Returns the symbol of the token, usually a shorter version of the name. - function symbol() public view virtual returns (string memory) { - return _symbol; + /** + * @notice See {IEncryptedERC20-approve}. + */ + function approve(address spender, euint64 amount) public virtual returns (bool) { + _isSenderAllowedForAmount(amount); + address owner = msg.sender; + _approve(owner, spender, amount); + emit Approval(owner, spender); + return true; } - // Returns the total supply of the token. - function totalSupply() public view virtual returns (uint64) { - return _totalSupply; + /** + * @notice See {IEncryptedERC20-transfer}. + */ + function transfer(address to, einput encryptedAmount, bytes calldata inputProof) public virtual returns (bool) { + transfer(to, TFHE.asEuint64(encryptedAmount, inputProof)); + return true; } - // Increase sender's balance by the given `amount`. - function _mint(uint64 amount, address to) internal virtual { - balances[to] = TFHE.add(balances[to], amount); // overflow impossible because of next line - _totalSupply = _totalSupply + amount; - emit Mint(to, amount); - } + /** + * @notice See {IEncryptedERC20-transfer}. + */ + function transfer(address to, euint64 amount) public virtual returns (bool) { + _isSenderAllowedForAmount(amount); - // Transfers an encrypted amount from the message sender address to the `to` address. - function transfer(address to, bytes calldata encryptedAmount) public virtual returns (bool) { - transfer(to, TFHE.asEuint64(encryptedAmount)); + /// Make sure the owner has enough tokens. + ebool canTransfer = TFHE.le(amount, _balances[msg.sender]); + _transfer(msg.sender, to, amount, canTransfer); return true; } - // Transfers an amount from the message sender address to the `to` address. - function transfer(address to, euint64 amount) public virtual returns (bool) { - // makes sure the owner has enough tokens - ebool canTransfer = TFHE.le(amount, balances[msg.sender]); - euint8 errorCode = defineErrorIfNot(canTransfer, uint8(ErrorCodes.UNSUFFICIENT_BALANCE)); - _transfer(msg.sender, to, amount, canTransfer, errorCode); + /** + * @notice See {IEncryptedERC20-transferFrom}. + */ + function transferFrom( + address from, + address to, + einput encryptedAmount, + bytes calldata inputProof + ) public virtual returns (bool) { + transferFrom(from, to, TFHE.asEuint64(encryptedAmount, inputProof)); return true; } - // Returns the balance of the caller encrypted under the provided public key. - function balanceOf( - address wallet, - bytes32 publicKey, - bytes calldata signature - ) public view virtual onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - require(wallet == msg.sender, "User cannot reencrypt a non-owned wallet balance"); - return TFHE.reencrypt(balances[wallet], publicKey, 0); + /** + * @notice See {IEncryptedERC20-transferFrom}. + */ + function transferFrom(address from, address to, euint64 amount) public virtual returns (bool) { + _isSenderAllowedForAmount(amount); + address spender = msg.sender; + ebool isTransferable = _updateAllowance(from, spender, amount); + _transfer(from, to, amount, isTransferable); + return true; } - // Returns the encrypted balance of the caller. - function balanceOfMe() public view virtual returns (euint64) { - return balances[msg.sender]; + /** + * @notice See {IEncryptedERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual returns (euint64) { + return _allowance(owner, spender); } - // Sets the `encryptedAmount` as the allowance of `spender` over the caller's tokens. - function approve(address spender, bytes calldata encryptedAmount) public virtual returns (bool) { - approve(spender, TFHE.asEuint64(encryptedAmount)); - return true; + /** + * @notice See {IEncryptedERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual returns (euint64) { + return _balances[account]; } - // Sets the `amount` as the allowance of `spender` over the caller's tokens. - function approve(address spender, euint64 amount) public virtual returns (bool) { - address owner = msg.sender; - _approve(owner, spender, amount); - emit Approval(owner, spender); - return true; + /** + * @notice See {IEncryptedERC20-decimals}. + */ + function decimals() public view virtual returns (uint8) { + return 6; } - // Returns the remaining number of tokens that `spender` is allowed to spend - // on behalf of the `owner`. The returned ciphertext is under the caller's `publicKey`. - function allowance( - address owner, - address spender, - bytes32 publicKey, - bytes calldata signature - ) public view virtual onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - require(owner == msg.sender || spender == msg.sender, "Caller must be owner or spender"); - return TFHE.reencrypt(_allowance(owner, spender), publicKey); + /** + * @notice See {IEncryptedERC20-name}. + */ + function name() public view virtual returns (string memory) { + return _name; } - // Transfers `encryptedAmount` tokens using the caller's allowance. - function transferFrom(address from, address to, bytes calldata encryptedAmount) public virtual returns (bool) { - transferFrom(from, to, TFHE.asEuint64(encryptedAmount)); - return true; + /** + * @notice See {IEncryptedERC20-symbol}. + */ + function symbol() public view virtual returns (string memory) { + return _symbol; } - // Transfers `amount` tokens using the caller's allowance. - function transferFrom(address from, address to, euint64 amount) public virtual returns (bool) { - address spender = msg.sender; - (ebool isTransferable, euint8 errorCode) = _updateAllowance(from, spender, amount); - _transfer(from, to, amount, isTransferable, errorCode); - return true; + /** + * @notice See {IEncryptedERC20-totalSupply}. + */ + function totalSupply() public view virtual returns (uint64) { + return _totalSupply; } function _approve(address owner, address spender, euint64 amount) internal virtual { - allowances[owner][spender] = amount; + _allowances[owner][spender] = amount; + TFHE.allowThis(amount); + TFHE.allow(amount, owner); + TFHE.allow(amount, spender); } - function _allowance(address owner, address spender) internal view virtual returns (euint64) { - if (TFHE.isInitialized(allowances[owner][spender])) { - return allowances[owner][spender]; - } else { - return TFHE.asEuint64(0); + /** + * @dev It does not incorporate any overflow check. It must be implemented + * by the function calling it. + */ + function _unsafeMint(address account, euint64 amount) internal virtual { + _balances[msg.sender] = TFHE.add(_balances[account], amount); + TFHE.allowThis(_balances[account]); + TFHE.allow(_balances[account], account); + emit Transfer(address(0), account); + } + + function _transfer(address from, address to, euint64 amount, ebool isTransferable) internal virtual { + _transferNoEvent(from, to, amount, isTransferable); + emit Transfer(from, to); + } + + function _transferNoEvent(address from, address to, euint64 amount, ebool isTransferable) internal virtual { + if (from == address(0)) { + revert SenderAddressNull(); } + + if (to == address(0)) { + revert ReceiverAddressNull(); + } + + /// Add to the balance of `to` and subract from the balance of `from`. + euint64 transferValue = TFHE.select(isTransferable, amount, TFHE.asEuint64(0)); + euint64 newBalanceTo = TFHE.add(_balances[to], transferValue); + _balances[to] = newBalanceTo; + TFHE.allowThis(newBalanceTo); + TFHE.allow(newBalanceTo, to); + euint64 newBalanceFrom = TFHE.sub(_balances[from], transferValue); + _balances[from] = newBalanceFrom; + TFHE.allowThis(newBalanceFrom); + TFHE.allow(newBalanceFrom, from); } - function _updateAllowance(address owner, address spender, euint64 amount) internal virtual returns (ebool, euint8) { + function _updateAllowance(address owner, address spender, euint64 amount) internal virtual returns (ebool) { euint64 currentAllowance = _allowance(owner, spender); - // makes sure the allowance suffices + /// Make sure sure the allowance suffices. ebool allowedTransfer = TFHE.le(amount, currentAllowance); - euint8 errorCode = defineErrorIfNot(allowedTransfer, uint8(ErrorCodes.UNSUFFICIENT_APPROVAL)); - // makes sure the owner has enough tokens - ebool canTransfer = TFHE.le(amount, balances[owner]); + /// Make sure the owner has enough tokens. + ebool canTransfer = TFHE.le(amount, _balances[owner]); ebool isTransferable = TFHE.and(canTransfer, allowedTransfer); - _approve(owner, spender, TFHE.select(isTransferable, currentAllowance - amount, currentAllowance)); - ebool isNotTransferableButIsApproved = TFHE.and(TFHE.not(canTransfer), allowedTransfer); - errorCode = changeErrorIf( - isNotTransferableButIsApproved, // should indeed check that spender is approved to not leak information - // on balance of `from` to unauthorized spender via calling reencryptTransferError afterwards - uint8(ErrorCodes.UNSUFFICIENT_BALANCE), - errorCode - ); - return (isTransferable, errorCode); - } - - // Transfers an encrypted amount. - function _transfer( - address from, - address to, - euint64 amount, - ebool isTransferable, - euint8 errorCode - ) internal virtual { - // Add to the balance of `to` and subract from the balance of `from`. - euint64 amountTransferred = TFHE.select(isTransferable, amount, TFHE.asEuint64(0)); - balances[to] = balances[to] + amountTransferred; - balances[from] = balances[from] - amountTransferred; - uint256 transferId = saveError(errorCode); - emit Transfer(transferId, from, to); - AllowedErrorReencryption memory allowedErrorReencryption = AllowedErrorReencryption( - msg.sender, - getError(transferId) - ); - allowedErrorReencryptions[transferId] = allowedErrorReencryption; - } - - // Returns the error code corresponding to transferId. - // The returned ciphertext is under the caller's `publicKey`. - function reencryptError( - uint256 transferId, - bytes32 publicKey, - bytes calldata signature - ) external view virtual onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - AllowedErrorReencryption memory allowedErrorReencryption = allowedErrorReencryptions[transferId]; - euint8 errorCode = allowedErrorReencryption.errorCode; - require(TFHE.isInitialized(errorCode), "Invalid transferId"); - require(msg.sender == allowedErrorReencryption.spender, "Only spender can reencrypt his error"); - return TFHE.reencrypt(errorCode, publicKey); + _approve(owner, spender, TFHE.select(isTransferable, TFHE.sub(currentAllowance, amount), currentAllowance)); + return isTransferable; + } + + function _allowance(address owner, address spender) internal view virtual returns (euint64) { + return _allowances[owner][spender]; + } + + function _isSenderAllowedForAmount(euint64 amount) internal view virtual { + if (!TFHE.isSenderAllowed(amount)) { + revert TFHESenderNotAllowed(); + } } } diff --git a/contracts/token/ERC20/IEncryptedERC20.sol b/contracts/token/ERC20/IEncryptedERC20.sol new file mode 100644 index 0000000..16c9a2d --- /dev/null +++ b/contracts/token/ERC20/IEncryptedERC20.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; + +/** + * @title IEncryptedERC20 + * @notice Interface that defines ERC20-like tokens with encrypted balances. + */ +interface IEncryptedERC20 { + /** + * @notice Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. + */ + event Approval(address indexed owner, address indexed spender); + + /** + * @notice Emitted when tokens are moved from one account (`from`) to + * another (`to`). + */ + event Transfer(address indexed from, address indexed to); + + /** + * @notice Returned when receiver is address(0). + */ + error ReceiverAddressNull(); + + /** + * @notice Returned when sender is address(0). + */ + error SenderAddressNull(); + + /** + * @notice Sets the `encryptedAmount` as the allowance of `spender` over the caller's tokens. + */ + function approve(address spender, einput encryptedAmount, bytes calldata inputProof) external returns (bool); + + /** + * @notice Sets the `amount` as the allowance of `spender` over the caller's tokens. + */ + function approve(address spender, euint64 amount) external returns (bool); + + /** + * @notice Transfers an encrypted amount from the message sender address to the `to` address. + */ + function transfer(address to, einput encryptedAmount, bytes calldata inputProof) external returns (bool); + + /** + * @notice Transfers an amount from the message sender address to the `to` address. + */ + function transfer(address to, euint64 amount) external returns (bool); + + /** + * @notice Transfers `amount` tokens using the caller's allowance. + */ + function transferFrom(address from, address to, euint64 amount) external returns (bool); + + /** + * @notice Transfers `encryptedAmount` tokens using the caller's allowance. + */ + function transferFrom( + address from, + address to, + einput encryptedAmount, + bytes calldata inputProof + ) external returns (bool); + + /** + * @notice Returns the remaining number of tokens that `spender` is allowed to spend + on behalf of the caller. + */ + function allowance(address owner, address spender) external view returns (euint64); + + /** + * @notice Returns the balance handle of the caller. + */ + function balanceOf(address wallet) external view returns (euint64); + + /** + * @notice Returns the number of decimals. + */ + function decimals() external view returns (uint8); + + /** + * @notice Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @notice Returns the symbol of the token, usually a shorter version of the name. + */ + function symbol() external view returns (string memory); + + /** + * @notice Returns the total supply of the token. + */ + function totalSupply() external view returns (uint64); +} diff --git a/contracts/token/ERC20/extensions/EncryptedERC20Mintable.sol b/contracts/token/ERC20/extensions/EncryptedERC20Mintable.sol index 2afa0e5..ec9ee0a 100644 --- a/contracts/token/ERC20/extensions/EncryptedERC20Mintable.sol +++ b/contracts/token/ERC20/extensions/EncryptedERC20Mintable.sol @@ -1,19 +1,42 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; -pragma solidity ^0.8.20; +import "fhevm/lib/TFHE.sol"; +import { Ownable2Step, Ownable } from "@openzeppelin/contracts/access/Ownable2Step.sol"; -import "../EncryptedERC20.sol"; -import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import { EncryptedERC20 } from "../EncryptedERC20.sol"; -contract EncryptedERC20Mintable is Ownable2Step, EncryptedERC20 { +/** + * @title EncryptedERC20Mintable + * @notice This contract inherits EncryptedERC20. + * @dev It allows an owner to mint tokens. Mint amounts are public. + */ +abstract contract EncryptedERC20Mintable is Ownable2Step, EncryptedERC20 { + /** + * @notice Emitted when `amount` tokens are minted to one account (`to`). + */ + event Mint(address indexed to, uint64 amount); + + /** + * @param name_ Name of the token. + * @param symbol_ Symbol. + * @param owner_ Owner address. + */ constructor( string memory name_, string memory symbol_, - address owner - ) Ownable(owner) EncryptedERC20(name_, symbol_) {} + address owner_ + ) Ownable(owner_) EncryptedERC20(name_, symbol_) {} - // Increase owner's balance by the given `mintedAmount`. - function mint(uint64 mintedAmount, address to) public virtual onlyOwner { - _mint(mintedAmount, to); + /** + * @notice Mint tokens. + * @param amount Amount of tokens to mint. + */ + function mint(uint64 amount) public virtual onlyOwner { + _unsafeMint(msg.sender, TFHE.asEuint64(amount)); + /// @dev Since _totalSupply is not encrypted and _totalSupply >= balances[msg.sender], + /// the next line contains an overflow check for the encrypted operation above. + _totalSupply = _totalSupply + amount; + emit Mint(msg.sender, amount); } } diff --git a/contracts/token/ERC20/extensions/EncryptedERC20WithErrors.sol b/contracts/token/ERC20/extensions/EncryptedERC20WithErrors.sol new file mode 100644 index 0000000..ee11059 --- /dev/null +++ b/contracts/token/ERC20/extensions/EncryptedERC20WithErrors.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import { EncryptedERC20 } from "../EncryptedERC20.sol"; +import { EncryptedErrors } from "../../../utils/EncryptedErrors.sol"; + +/** + * @title EncryptedERC20WithErrors + * @notice This contract implements an encrypted ERC20-like token with confidential balances using + * Zama's FHE (Fully Homomorphic Encryption) library. + * @dev It supports standard ERC20 functions such as transferring tokens, minting, + * and setting allowances, but uses encrypted data types. + * The total supply is not encrypted. + * It also supports error handling for encrypted errors. + */ + +abstract contract EncryptedERC20WithErrors is EncryptedERC20, EncryptedErrors { + /** + * @notice Emitted when tokens are moved from one account (`from`) to + * another (`to`). + */ + event TransferWithErrorHandling(address indexed from, address indexed to, uint256 transferId); + + /** + * @notice Error codes allow tracking (in the storage) whether a transfer worked. + * @dev NO_ERROR: the transfer worked as expected + * UNSUFFICIENT_BALANCE: the transfer failed because the + * from balances were strictly inferior to the amount to transfer. + * UNSUFFICIENT_APPROVAL: the transfer failed because the sender allowance + * was strictly lower than the amount to transfer. + */ + enum ErrorCodes { + NO_ERROR, + UNSUFFICIENT_BALANCE, + UNSUFFICIENT_APPROVAL + } + + /// @notice Keeps track of the current transferId. + uint256 private _transferIdCounter; + + /// @notice A mapping from transferId to the error code. + mapping(uint256 transferId => euint8 errorCode) internal _errorCodeForTransferId; + + /** + * @param name_ Name of the token. + * @param symbol_ Symbol. + */ + constructor( + string memory name_, + string memory symbol_ + ) EncryptedERC20(name_, symbol_) EncryptedErrors(uint8(type(ErrorCodes).max)) {} + + /** + * @notice See {IEncryptedERC20-transfer}. + */ + function transfer(address to, euint64 amount) public virtual override returns (bool) { + _isSenderAllowedForAmount(amount); + + /// Check whether the owner has enough tokens. + ebool canTransfer = TFHE.le(amount, _balances[msg.sender]); + + euint8 errorCode = TFHE.select( + canTransfer, + _errorCodes[uint8(ErrorCodes.NO_ERROR)], + _errorCodes[uint8(ErrorCodes.UNSUFFICIENT_BALANCE)] + ); + + _transferWithErrorCode(msg.sender, to, amount, canTransfer, errorCode); + return true; + } + + /** + * @notice See {IEncryptedERC20-transferFrom}. + */ + function transferFrom(address from, address to, euint64 amount) public virtual override returns (bool) { + _isSenderAllowedForAmount(amount); + address spender = msg.sender; + (ebool isTransferable, euint8 errorCode) = _updateAllowanceWithErrorCode(from, spender, amount); + _transferWithErrorCode(from, to, amount, isTransferable, errorCode); + return true; + } + + /** + * @notice Returns the error code corresponding to `transferId`. + */ + function getErrorCodeForTransferId(uint256 transferId) public view virtual returns (euint8 errorCode) { + return _errorCodeForTransferId[transferId]; + } + + function _transferWithErrorCode( + address from, + address to, + euint64 amount, + ebool isTransferable, + euint8 errorCode + ) internal virtual { + _transferNoEvent(from, to, amount, isTransferable); + emit TransferWithErrorHandling(from, to, _transferIdCounter); + + /// Set the error code in the storage and increment. + _errorCodeForTransferId[_transferIdCounter++] = errorCode; + + TFHE.allowThis(errorCode); + TFHE.allow(errorCode, from); + TFHE.allow(errorCode, to); + } + + function _updateAllowanceWithErrorCode( + address owner, + address spender, + euint64 amount + ) internal virtual returns (ebool isTransferable, euint8 errorCode) { + euint64 currentAllowance = _allowance(owner, spender); + + /// Make sure sure the allowance suffices. + ebool allowedTransfer = TFHE.le(amount, currentAllowance); + + errorCode = TFHE.select( + allowedTransfer, + _errorCodes[uint8(ErrorCodes.UNSUFFICIENT_APPROVAL)], + _errorCodes[uint8(ErrorCodes.NO_ERROR)] + ); + + /// Make sure the owner has enough tokens. + ebool canTransfer = TFHE.le(amount, _balances[owner]); + + errorCode = TFHE.select( + TFHE.eq(errorCode, 0), + TFHE.select( + canTransfer, + _errorCodes[uint8(ErrorCodes.UNSUFFICIENT_BALANCE)], + _errorCodes[uint8(ErrorCodes.NO_ERROR)] + ), + errorCode + ); + + isTransferable = TFHE.and(canTransfer, allowedTransfer); + _approve(owner, spender, TFHE.select(isTransferable, TFHE.sub(currentAllowance, amount), currentAllowance)); + } +} diff --git a/contracts/token/ERC20/extensions/EncryptedERC20WithErrorsMintable.sol b/contracts/token/ERC20/extensions/EncryptedERC20WithErrorsMintable.sol new file mode 100644 index 0000000..316f381 --- /dev/null +++ b/contracts/token/ERC20/extensions/EncryptedERC20WithErrorsMintable.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import { Ownable2Step, Ownable } from "@openzeppelin/contracts/access/Ownable2Step.sol"; + +import { EncryptedERC20WithErrors } from "./EncryptedERC20WithErrors.sol"; + +/** + * @title EncryptedERC20WithErrorsMintable + * @notice This contract inherits EncryptedERC20WithErrors. + * @dev It allows an owner to mint tokens. Mint amounts are public. + */ +abstract contract EncryptedERC20WithErrorsMintable is Ownable2Step, EncryptedERC20WithErrors { + /** + * @notice Emitted when `amount` tokens are minted to one account (`to`). + */ + event Mint(address indexed to, uint64 amount); + + /** + * @param name_ Name of the token. + * @param symbol_ Symbol. + * @param owner_ Owner address. + */ + constructor( + string memory name_, + string memory symbol_, + address owner_ + ) Ownable(owner_) EncryptedERC20WithErrors(name_, symbol_) {} + + /** + * @notice Mint tokens. + * @param amount Amount of tokens to mint. + */ + function mint(uint64 amount) public virtual onlyOwner { + _unsafeMint(msg.sender, TFHE.asEuint64(amount)); + /// @dev Since _totalSupply is not encrypted and _totalSupply >= balances[msg.sender], + /// the next line contains an overflow check for the encrypted operation above. + _totalSupply = _totalSupply + amount; + emit Mint(msg.sender, amount); + } +} diff --git a/contracts/utils/EncryptedErrors.sol b/contracts/utils/EncryptedErrors.sol index 4f9ae2c..f415790 100644 --- a/contracts/utils/EncryptedErrors.sol +++ b/contracts/utils/EncryptedErrors.sol @@ -1,140 +1,49 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.20; +pragma solidity ^0.8.24; import "fhevm/lib/TFHE.sol"; /** - * This abstract contract is used for error handling in the fhEVM. - * - * Error codes are trivially encrypted during construction inside the `errorCodes` array. - * - * WARNING: `errorCodes[0]` should always refer to the `NO_ERROR` code, by default. - * + * @notice This abstract contract is used for error handling in the fhEVM. + * Error codes are encrypted in the constructor inside the `errorCodes` mapping. + * @dev `errorCodes[0]` should always refer to the `NO_ERROR` code, by default. */ abstract contract EncryptedErrors { - uint8 private immutable totalNumErrors; - euint8[] private errorCodes; - uint256 private counterErrors; // used to keep track of each error index + /// @notice The total number of errors is equal to zero. + error TotalNumberErrorsEqualToZero(); + + /// @notice Total number of errors. + uint8 private immutable _TOTAL_NUMBER_ERRORS; - // A mapping from errorId to the errorCode - mapping(uint256 => euint8) private errorCodesMapping; + /// @notice Mapping of error codes. + /// @dev It does not use arrays they are more expensive than mappings. + mapping(uint8 errorCode => euint8 encryptedErrorCode) internal _errorCodes; /** * @notice Sets the non-null value for `numErrors` corresponding to the total number of errors. - * @param numErrors the total number of different errors. - * @dev `numErrors` must be non-null, note that `errorCodes[0]` corresponds to the `NO_ERROR` code. + * @param totalNumberErrors_ total number of different errors. + * @dev `numErrors` must be non-null (`errorCodes[0]` corresponds to the `NO_ERROR` code). */ - constructor(uint8 numErrors) { - require(numErrors != 0, "numErrors must be greater than 0"); - for (uint256 i = 0; i <= numErrors; i++) { - errorCodes.push(TFHE.asEuint8(i)); + constructor(uint8 totalNumberErrors_) { + if (totalNumberErrors_ == 0) { + revert TotalNumberErrorsEqualToZero(); } - totalNumErrors = numErrors; - } - /** - * @notice Returns the encrypted error code at index `indexCode`. - * @param indexCode the index of the requested error code. - * @return the encrypted error code located at `indexCode`. - */ - function getErrorCode(uint8 indexCode) internal view returns (euint8) { - return errorCodes[indexCode]; - } - - /** - * @notice Returns the total number of error codes currently stored in `errorCodesMapping`. - * @return the number of error codes stored in the `errorCodesMapping` mapping. - */ - function getErrorCounter() internal view returns (uint256) { - return counterErrors; - } - - /** - * @notice Returns the total number of the possible errors. - * @return the total number of the different possible errors. - */ - function getNumErrors() internal view returns (uint8) { - return totalNumErrors; - } - - /** - * @notice Returns the encrypted error code which was stored in the mapping at key `errorId`. - * @param errorId the requested key stored in the `errorCodesMapping` mapping. - * @return the encrypted error code located at the `errorId` key. - * @dev `errorId` must be a valid id, i.e below the error counter. - */ - function getError(uint256 errorId) internal view returns (euint8) { - require(errorId < counterErrors, "errorId must be a valid id"); - return errorCodesMapping[errorId]; - } - - /** - * @notice Computes an encrypted error code, result will be either a reencryption of - * `errorCodes[indexCode]` if `condition` is an encrypted `true` or of `NO_ERROR` otherwise. - * @param condition the encrypted boolean used in the cmux. - * @param indexCode the index of the selected error code if `condition` encrypts `true`. - * @return the reencrypted error code depending on `condition` value. - * @dev `indexCode` must be non-null and below the total number of error codes. - */ - function defineErrorIf(ebool condition, uint8 indexCode) internal view returns (euint8) { - require(indexCode != 0, "indexCode must be greater than 0"); - require(indexCode <= totalNumErrors, "indexCode must be a valid error code"); - euint8 errorCode = TFHE.select(condition, errorCodes[indexCode], errorCodes[0]); - return errorCode; - } - - /** - * @notice Does the opposite of `defineErrorIf`, i.e result will be either a reencryption of - * `errorCodes[indexCode]` if `condition` is an encrypted `false` or of `NO_ERROR` otherwise. - * @param condition the encrypted boolean used in the cmux. - * @param indexCode the index of the selected error code if `condition` encrypts `false`. - * @return the reencrypted error code depending on `condition` value. - * @dev `indexCode` must be non-null and below the total number of error codes. - */ - function defineErrorIfNot(ebool condition, uint8 indexCode) internal view returns (euint8) { - require(indexCode != 0, "indexCode must be greater than 0"); - require(indexCode <= totalNumErrors, "indexCode must be a valid error code"); - euint8 errorCode = TFHE.select(condition, errorCodes[0], errorCodes[indexCode]); - return errorCode; - } - - /** - * @notice Computes an encrypted error code, result will be either a reencryption of - * `errorCodes[indexCode]` if `condition` is an encrypted `true` or of `errorCode` otherwise. - * @param condition the encrypted boolean used in the cmux. - * @param errorCode the selected error code if `condition` encrypts `true`. - * @return the reencrypted error code depending on `condition` value. - * @dev `indexCode` must be below the total number of error codes. - */ - function changeErrorIf(ebool condition, uint8 indexCode, euint8 errorCode) internal view returns (euint8) { - require(indexCode <= totalNumErrors, "indexCode must be a valid error code"); - return TFHE.select(condition, errorCodes[indexCode], errorCode); - } + for (uint8 i; i <= totalNumberErrors_; i++) { + euint8 errorCode = TFHE.asEuint8(i); + _errorCodes[i] = errorCode; + TFHE.allowThis(errorCode); + } - /** - * @notice Does the opposite of `changeErrorIf`, i.e result will be either a reencryption of - * `errorCodes[indexCode]` if `condition` is an encrypted `false` or of `errorCode` otherwise. - * @param condition the encrypted boolean used in the cmux. - * @param errorCode the selected error code if `condition` encrypts `false`. - * @return the reencrypted error code depending on `condition` value. - * @dev `indexCode` must be below the total number of error codes. - */ - function changeErrorIfNot(ebool condition, uint8 indexCode, euint8 errorCode) internal view returns (euint8) { - require(indexCode <= totalNumErrors, "indexCode must be a valid error code"); - return TFHE.select(condition, errorCode, errorCodes[indexCode]); + _TOTAL_NUMBER_ERRORS = totalNumberErrors_; } /** - * @notice Saves `errorCode` in storage, in the `errorCodesMapping` mapping, at the lowest unused key. - * This is the only stateful function of `EncryptedErrors` abstract contract. - * @param errorCode the encrypted error code to be saved in storage. - * @return the `errorId` key in `errorCodesMapping` where `errorCode` is stored. + * @notice Returns the total number of errors. + * @return totalNumberErrors total number of errors. + * @dev It does not count `NO_ERROR` as one of the errors. */ - function saveError(euint8 errorCode) internal returns (uint256) { - uint256 errorId = counterErrors; - counterErrors++; - errorCodesMapping[errorId] = errorCode; - return errorId; + function getTotalNumberErrors() external view returns (uint8 totalNumberErrors) { + return _TOTAL_NUMBER_ERRORS; } } diff --git a/hardhat.config.ts b/hardhat.config.ts index 8edd0d9..9dae56b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,73 +1,52 @@ import "@nomicfoundation/hardhat-toolbox"; +import "@openzeppelin/hardhat-upgrades"; import dotenv from "dotenv"; -import * as fs from "fs"; +import * as fs from "fs-extra"; import "hardhat-deploy"; -import "hardhat-preprocessor"; -import { TASK_PREPROCESS } from "hardhat-preprocessor"; +import "hardhat-ignore-warnings"; import type { HardhatUserConfig } from "hardhat/config"; +import { extendProvider } from "hardhat/config"; import { task } from "hardhat/config"; import type { NetworkUserConfig } from "hardhat/types"; import { resolve } from "path"; import * as path from "path"; +import CustomProvider from "./CustomProvider"; +// Adjust the import path as needed import "./tasks/accounts"; import "./tasks/getEthereumAddress"; -import "./tasks/taskOracleRelayer"; +import "./tasks/taskDeploy"; +import "./tasks/taskGatewayRelayer"; +import "./tasks/taskTFHE"; -function getAllSolidityFiles(dir: string, fileList: string[] = []): string[] { - fs.readdirSync(dir).forEach((file) => { - const filePath = path.join(dir, file); - if (fs.statSync(filePath).isDirectory()) { - getAllSolidityFiles(filePath, fileList); - } else if (filePath.endsWith(".sol")) { - fileList.push(filePath); - } - }); - return fileList; -} +extendProvider(async (provider) => { + const newProvider = new CustomProvider(provider); + return newProvider; +}); -task("coverage-mock", "Run coverage after running pre-process task").setAction(async function (args, env) { - const contractsPath = path.join(env.config.paths.root, "contracts/"); - const solidityFiles = getAllSolidityFiles(contractsPath); - const originalContents: Record = {}; - solidityFiles.forEach((filePath) => { - originalContents[filePath] = fs.readFileSync(filePath, { encoding: "utf8" }); - }); +task("compile:specific", "Compiles only the specified contract") + .addParam("contract", "The contract's path") + .setAction(async ({ contract }, hre) => { + // Adjust the configuration to include only the specified contract + hre.config.paths.sources = contract; - try { - await env.run(TASK_PREPROCESS); - await env.run("coverage"); - } finally { - // Restore original files - for (const filePath in originalContents) { - fs.writeFileSync(filePath, originalContents[filePath], { encoding: "utf8" }); - } - } -}); + await hre.run("compile"); + }); const dotenvConfigPath: string = process.env.DOTENV_CONFIG_PATH || "./.env"; dotenv.config({ path: resolve(__dirname, dotenvConfigPath) }); +// Ensure that we have all the environment variables we need. const mnemonic: string | undefined = process.env.MNEMONIC; if (!mnemonic) { throw new Error("Please set your MNEMONIC in a .env file"); } -const network = process.env.HARDHAT_NETWORK; - -function getRemappings() { - return fs - .readFileSync("remappings.txt", "utf8") - .split("\n") - .filter(Boolean) // remove empty lines - .map((line: string) => line.trim().split("=")); -} - const chainIds = { zama: 8009, local: 9000, - localNetwork1: 9000, - multipleValidatorTestnet: 8009, + localCoprocessor: 12345, + sepolia: 11155111, }; function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { @@ -76,15 +55,14 @@ function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { case "local": jsonRpcUrl = "http://localhost:8545"; break; - case "localNetwork1": - jsonRpcUrl = "http://127.0.0.1:9650/ext/bc/fhevm/rpc"; - break; - case "multipleValidatorTestnet": - jsonRpcUrl = "https://rpc.fhe-ethermint.zama.ai"; + case "localCoprocessor": + jsonRpcUrl = "http://localhost:8745"; break; case "zama": jsonRpcUrl = "https://devnet.zama.ai"; break; + case "sepolia": + jsonRpcUrl = process.env.SEPOLIA_RPC_URL!; } return { accounts: { @@ -97,59 +75,67 @@ function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { }; } +task("coverage").setAction(async (taskArgs, hre, runSuper) => { + hre.config.networks.hardhat.allowUnlimitedContractSize = true; + hre.config.networks.hardhat.blockGasLimit = 1099511627775; + await runSuper(taskArgs); +}); + +function replaceImportStatement(filePath: string, oldImport: string, newImport: string): void { + try { + let fileContent = fs.readFileSync(filePath, "utf-8"); + fileContent = fileContent.replace(oldImport, newImport); + fs.writeFileSync(filePath, fileContent, "utf-8"); + } catch (error) { + console.error(`Error updating file: ${error}`); + } +} + task("test", async (taskArgs, hre, runSuper) => { // Run modified test task - - if (network === "hardhat") { + if (hre.network.name === "hardhat") { // in fhevm mode all this block is done when launching the node via `pnmp fhevm:start` - const privKeyDeployer = process.env.PRIVATE_KEY_ORACLE_DEPLOYER; - const privKeyOwner = process.env.PRIVATE_KEY_ORACLE_OWNER; - const privKeyRelayer = process.env.PRIVATE_KEY_ORACLE_RELAYER; - const deployerAddress = new hre.ethers.Wallet(privKeyDeployer!).address; - const ownerAddress = new hre.ethers.Wallet(privKeyOwner!).address; - const relayerAddress = new hre.ethers.Wallet(privKeyRelayer!).address; - - await hre.run("task:computePredeployAddress", { privateKey: privKeyDeployer }); - - const bal = "0x1000000000000000000000000000000000000000"; - const p1 = hre.network.provider.send("hardhat_setBalance", [deployerAddress, bal]); - const p2 = hre.network.provider.send("hardhat_setBalance", [ownerAddress, bal]); - const p3 = hre.network.provider.send("hardhat_setBalance", [relayerAddress, bal]); - await Promise.all([p1, p2, p3]); - await hre.run("compile"); - await hre.run("task:deployOracle", { privateKey: privKeyDeployer, ownerAddress: ownerAddress }); - - const parsedEnv = dotenv.parse(fs.readFileSync("node_modules/fhevm/oracle/.env.oracle")); - const oraclePredeployAddress = parsedEnv.ORACLE_CONTRACT_PREDEPLOY_ADDRESS; - - await hre.run("task:addRelayer", { - privateKey: privKeyOwner, - oracleAddress: oraclePredeployAddress, - relayerAddress: relayerAddress, + const privKeyGatewayDeployer = process.env.PRIVATE_KEY_GATEWAY_DEPLOYER; + const privKeyFhevmDeployer = process.env.PRIVATE_KEY_FHEVM_DEPLOYER; + await hre.run("task:computeGatewayAddress", { privateKey: privKeyGatewayDeployer }); + await hre.run("task:computeACLAddress", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:computeTFHEExecutorAddress", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:computeKMSVerifierAddress", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:computeInputVerifierAddress", { privateKey: privKeyFhevmDeployer, useAddress: false }); + await hre.run("task:computeFHEPaymentAddress", { privateKey: privKeyFhevmDeployer }); + await hre.run("compile:specific", { contract: "contracts/" }); + const sourceDir = path.resolve(__dirname, "node_modules/fhevm-core-contracts/"); + const destinationDir = path.resolve(__dirname, "fhevmTemp/"); + fs.copySync(sourceDir, destinationDir, { dereference: true }); + + const sourceDir2 = path.resolve("./node_modules/fhevm/gateway/GatewayContract.sol"); + const destinationFilePath = path.join(destinationDir, "GatewayContract.sol"); + fs.copySync(sourceDir2, destinationFilePath, { dereference: true }); + const oldImport = `import "../lib/TFHE.sol";`; + const newImport = `import "fhevm/lib/TFHE.sol";`; + replaceImportStatement(destinationFilePath, oldImport, newImport); + const sourceDir3 = path.resolve("./node_modules/fhevm/gateway/IKMSVerifier.sol"); + const destinationFilePath3 = path.join(destinationDir, "IKMSVerifier.sol"); + fs.copySync(sourceDir3, destinationFilePath3, { dereference: true }); + + await hre.run("compile:specific", { contract: "fhevmTemp/" }); + await hre.run("task:faucetToPrivate", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:deployACL", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:deployTFHEExecutor", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:deployKMSVerifier", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:deployInputVerifier", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:deployFHEPayment", { privateKey: privKeyFhevmDeployer }); + await hre.run("task:addSigners", { + numSigners: process.env.NUM_KMS_SIGNERS!, + privateKey: privKeyFhevmDeployer, + useAddress: false, }); + await hre.run("task:launchFhevm", { skipGetCoin: false, useAddress: false }); } - await runSuper(); }); const config: HardhatUserConfig = { - preprocess: { - eachLine: () => ({ - transform: (line: string) => { - if (network === "hardhat") { - if (line.match(/".*.sol";$/)) { - for (const [from, to] of getRemappings()) { - if (line.includes(from)) { - line = line.replace(from, to); - break; - } - } - } - } - return line; - }, - }), - }, defaultNetwork: "local", namedAccounts: { deployer: 0, @@ -165,18 +151,17 @@ const config: HardhatUserConfig = { }, networks: { hardhat: { - gas: "auto", accounts: { count: 10, mnemonic, path: "m/44'/60'/0'/0", }, }, + sepolia: getChainConfig("sepolia"), zama: getChainConfig("zama"), localDev: getChainConfig("local"), local: getChainConfig("local"), - localNetwork1: getChainConfig("localNetwork1"), - multipleValidatorTestnet: getChainConfig("multipleValidatorTestnet"), + localCoprocessor: getChainConfig("localCoprocessor"), }, paths: { artifacts: "./artifacts", @@ -185,7 +170,7 @@ const config: HardhatUserConfig = { tests: "./test", }, solidity: { - version: "0.8.22", + version: "0.8.24", settings: { metadata: { // Not including the metadata hash @@ -198,7 +183,12 @@ const config: HardhatUserConfig = { enabled: true, runs: 800, }, - evmVersion: "shanghai", + evmVersion: "cancun", + }, + }, + warnings: { + "*": { + "transient-storage": false, }, }, typechain: { diff --git a/package.json b/package.json index 516bbde..076d82b 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "fhevm-contracts", - "description": "fhEVM contracts", + "name": "@zama-ai/fhevm-contracts", + "description": "fhEVM contracts is a Solidity library for secure smart-contract development using fhEVM and TFHE.", "version": "0.1.0", "author": { - "name": "Zama", + "name": "zama-ai", "url": "https://github.com/zama-ai" }, "license": "BSD-3-Clause", @@ -13,13 +13,14 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.10", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@nomicfoundation/hardhat-verify": "^1.1.1", + "@openzeppelin/hardhat-upgrades": "^3.5.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typechain/ethers-v6": "^0.4.3", "@typechain/hardhat": "^8.0.3", "@types/chai": "^4.3.12", "@types/fs-extra": "^9.0.13", "@types/mocha": "^10.0.6", - "@types/node": "^18.19.23", + "@types/node": "^18.19.59", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "chai": "^4.4.1", @@ -28,12 +29,14 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^8.10.0", "ethers": "^6.11.1", - "fhevm": "^0.4.0", - "fhevmjs": "^0.4.0-7", + "fhevm": "^0.6.0-0", + "fhevm-core-contracts": "0.1.0-2", + "fhevmjs": "^0.6.0-4", "fs-extra": "^10.1.0", - "hardhat": "2.21.0", + "hardhat": "2.22.14", "hardhat-deploy": "^0.11.45", "hardhat-gas-reporter": "^1.0.10", + "hardhat-ignore-warnings": "^0.2.11", "hardhat-preprocessor": "^0.1.5", "lodash": "^4.17.21", "mocha": "^10.3.0", @@ -42,15 +45,16 @@ "rimraf": "^4.4.1", "solhint": "^3.6.2", "solhint-plugin-prettier": "^0.0.5", - "solidity-coverage": "0.8.6", - "solidity-docgen": "0.6.0-beta.36", + "solidity-coverage": "0.8.12", "ts-generator": "^0.1.1", "ts-node": "^10.9.2", "typechain": "^8.3.2", "typescript": "^5.4.2" }, "files": [ - "contracts" + "contracts/governance/", + "contracts/token/", + "contracts/utils/" ], "keywords": [ "blockchain", @@ -61,13 +65,14 @@ "solidity", "template", "typescript", - "typechain" + "typechain", + "tfhe" ], "publishConfig": { "access": "public" }, "scripts": { - "clean": "rimraf ./artifacts ./cache ./coverage ./types ./coverage.json && npm run typechain", + "clean": "rimraf ./fhevmTemp ./artifacts ./cache ./coverage ./types ./coverage.json && pnpm typechain", "compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile", "deploy:contracts": "hardhat deploy", "docgen": "hardhat docgen", @@ -79,7 +84,7 @@ "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain", "test": "hardhat test", "test:mock": "HARDHAT_NETWORK=hardhat npx hardhat test --network hardhat", - "coverage:mock": "HARDHAT_NETWORK=hardhat npx hardhat coverage-mock --network hardhat", + "coverage:mock": "npx hardhat coverage", "task:getEthereumAddress": "hardhat task:getEthereumAddress", "task:accounts": "hardhat task:accounts", "fhevm:start": "./launch-fhevm.sh", @@ -93,6 +98,9 @@ "fhevm:faucet:eve": "docker exec -i fhevm faucet $(npx hardhat task:getEthereumAddressEve)" }, "dependencies": { - "@openzeppelin/contracts": "^5.0.2" + "@openzeppelin/contracts-upgradeable": "5.0.2", + "@openzeppelin/contracts": "5.0.2", + "extra-bigint": "^1.1.18", + "sqlite3": "^5.1.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7fc87d..bde31ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,240 +1,3457 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@openzeppelin/contracts': - specifier: ^5.0.2 - version: 5.0.2 - -devDependencies: - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^2.0.6 - version: 2.0.6(@nomicfoundation/hardhat-ethers@3.0.5)(chai@4.4.1)(ethers@6.11.1)(hardhat@2.21.0) - '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.5 - version: 3.0.5(ethers@6.11.1)(hardhat@2.21.0) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.10 - version: 1.0.10(hardhat@2.21.0) - '@nomicfoundation/hardhat-toolbox': - specifier: ^3.0.0 - version: 3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.6)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomicfoundation/hardhat-network-helpers@1.0.10)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.12)(@types/mocha@10.0.6)(@types/node@18.19.23)(chai@4.4.1)(ethers@6.11.1)(hardhat-gas-reporter@1.0.10)(hardhat@2.21.0)(solidity-coverage@0.8.6)(ts-node@10.9.2)(typechain@8.3.2)(typescript@5.4.2) - '@nomicfoundation/hardhat-verify': - specifier: ^1.1.1 - version: 1.1.1(hardhat@2.21.0) - '@trivago/prettier-plugin-sort-imports': - specifier: ^4.3.0 - version: 4.3.0(prettier@2.8.8) - '@typechain/ethers-v6': - specifier: ^0.4.3 - version: 0.4.3(ethers@6.11.1)(typechain@8.3.2)(typescript@5.4.2) - '@typechain/hardhat': - specifier: ^8.0.3 - version: 8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.11.1)(hardhat@2.21.0)(typechain@8.3.2) - '@types/chai': - specifier: ^4.3.12 - version: 4.3.12 - '@types/fs-extra': - specifier: ^9.0.13 - version: 9.0.13 - '@types/mocha': - specifier: ^10.0.6 - version: 10.0.6 - '@types/node': - specifier: ^18.19.23 - version: 18.19.23 - '@typescript-eslint/eslint-plugin': - specifier: ^5.62.0 - version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.2) - '@typescript-eslint/parser': - specifier: ^5.62.0 - version: 5.62.0(eslint@8.57.0)(typescript@5.4.2) - chai: - specifier: ^4.4.1 - version: 4.4.1 - cross-env: - specifier: ^7.0.3 - version: 7.0.3 - dotenv: - specifier: ^16.4.5 - version: 16.4.5 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-prettier: - specifier: ^8.10.0 - version: 8.10.0(eslint@8.57.0) - ethers: - specifier: ^6.11.1 - version: 6.11.1 - fhevm: - specifier: ^0.4.0 - version: 0.4.0(hardhat@2.21.0) - fhevmjs: - specifier: ^0.4.0-7 - version: 0.4.0-7 - fs-extra: - specifier: ^10.1.0 - version: 10.1.0 - hardhat: - specifier: 2.21.0 - version: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) - hardhat-deploy: - specifier: ^0.11.45 - version: 0.11.45 - hardhat-gas-reporter: - specifier: ^1.0.10 - version: 1.0.10(hardhat@2.21.0) - hardhat-preprocessor: - specifier: ^0.1.5 - version: 0.1.5(hardhat@2.21.0) - lodash: - specifier: ^4.17.21 - version: 4.17.21 - mocha: - specifier: ^10.3.0 - version: 10.3.0 - prettier: - specifier: ^2.8.8 - version: 2.8.8 - prettier-plugin-solidity: - specifier: ^1.3.1 - version: 1.3.1(prettier@2.8.8) - rimraf: - specifier: ^4.4.1 - version: 4.4.1 - solhint: - specifier: ^3.6.2 - version: 3.6.2(typescript@5.4.2) - solhint-plugin-prettier: - specifier: ^0.0.5 - version: 0.0.5(prettier-plugin-solidity@1.3.1)(prettier@2.8.8) - solidity-coverage: - specifier: 0.8.6 - version: 0.8.6(hardhat@2.21.0) - solidity-docgen: - specifier: 0.6.0-beta.36 - version: 0.6.0-beta.36(hardhat@2.21.0) - ts-generator: - specifier: ^0.1.1 - version: 0.1.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@18.19.23)(typescript@5.4.2) - typechain: - specifier: ^8.3.2 - version: 8.3.2(typescript@5.4.2) - typescript: - specifier: ^5.4.2 - version: 5.4.2 +importers: + + .: + dependencies: + '@openzeppelin/contracts': + specifier: 5.0.2 + version: 5.0.2 + '@openzeppelin/contracts-upgradeable': + specifier: 5.0.2 + version: 5.0.2(@openzeppelin/contracts@5.0.2) + extra-bigint: + specifier: ^1.1.18 + version: 1.2.0 + sqlite3: + specifier: ^5.1.7 + version: 5.1.7 + devDependencies: + '@nomicfoundation/hardhat-chai-matchers': + specifier: ^2.0.6 + version: 2.0.6(@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(chai@4.4.1)(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.5 + version: 3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-network-helpers': + specifier: ^1.0.10 + version: 1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-toolbox': + specifier: ^3.0.0 + version: 3.0.0(sziado6kyyqqr3qor4olybdgcq) + '@nomicfoundation/hardhat-verify': + specifier: ^1.1.1 + version: 1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@openzeppelin/hardhat-upgrades': + specifier: ^3.5.0 + version: 3.5.0(@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(encoding@0.1.13)(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@trivago/prettier-plugin-sort-imports': + specifier: ^4.3.0 + version: 4.3.0(prettier@2.8.8) + '@typechain/ethers-v6': + specifier: ^0.4.3 + version: 0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2) + '@typechain/hardhat': + specifier: ^8.0.3 + version: 8.0.3(@typechain/ethers-v6@0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2))(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))(typechain@8.3.2(typescript@5.4.2)) + '@types/chai': + specifier: ^4.3.12 + version: 4.3.12 + '@types/fs-extra': + specifier: ^9.0.13 + version: 9.0.13 + '@types/mocha': + specifier: ^10.0.6 + version: 10.0.6 + '@types/node': + specifier: ^18.19.59 + version: 18.19.59 + '@typescript-eslint/eslint-plugin': + specifier: ^5.62.0 + version: 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.2))(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/parser': + specifier: ^5.62.0 + version: 5.62.0(eslint@8.57.0)(typescript@5.4.2) + chai: + specifier: ^4.4.1 + version: 4.4.1 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^8.10.0 + version: 8.10.0(eslint@8.57.0) + ethers: + specifier: ^6.11.1 + version: 6.11.1 + fhevm: + specifier: ^0.6.0-0 + version: 0.6.0-0 + fhevm-core-contracts: + specifier: 0.1.0-2 + version: 0.1.0-2 + fhevmjs: + specifier: ^0.6.0-4 + version: 0.6.0-4 + fs-extra: + specifier: ^10.1.0 + version: 10.1.0 + hardhat: + specifier: 2.22.14 + version: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) + hardhat-deploy: + specifier: ^0.11.45 + version: 0.11.45 + hardhat-gas-reporter: + specifier: ^1.0.10 + version: 1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + hardhat-ignore-warnings: + specifier: ^0.2.11 + version: 0.2.11 + hardhat-preprocessor: + specifier: ^0.1.5 + version: 0.1.5(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + lodash: + specifier: ^4.17.21 + version: 4.17.21 + mocha: + specifier: ^10.3.0 + version: 10.3.0 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + prettier-plugin-solidity: + specifier: ^1.3.1 + version: 1.3.1(prettier@2.8.8) + rimraf: + specifier: ^4.4.1 + version: 4.4.1 + solhint: + specifier: ^3.6.2 + version: 3.6.2(typescript@5.4.2) + solhint-plugin-prettier: + specifier: ^0.0.5 + version: 0.0.5(prettier-plugin-solidity@1.3.1(prettier@2.8.8))(prettier@2.8.8) + solidity-coverage: + specifier: 0.8.12 + version: 0.8.12(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + ts-generator: + specifier: ^0.1.1 + version: 0.1.1 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.59)(typescript@5.4.2) + typechain: + specifier: ^8.3.2 + version: 8.3.2(typescript@5.4.2) + typescript: + specifier: ^5.4.2 + version: 5.4.2 + +packages: + + '@aashutoshrathi/word-wrap@1.2.6': + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + + '@aws-crypto/sha256-js@1.2.2': + resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==} + + '@aws-crypto/util@1.2.2': + resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==} + + '@aws-sdk/types@3.679.0': + resolution: {integrity: sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + + '@babel/code-frame@7.23.5': + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.17.7': + resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.23.6': + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-environment-visitor@7.22.20': + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.23.0': + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.22.5': + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-split-export-declaration@7.22.6': + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.23.4': + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.22.20': + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.23.4': + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.0': + resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.24.0': + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.23.2': + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.17.0': + resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.24.0': + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.10.0': + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@ethereumjs/rlp@4.0.1': + resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} + engines: {node: '>=14'} + hasBin: true + + '@ethereumjs/util@8.1.0': + resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} + engines: {node: '>=14'} + + '@ethersproject/abi@5.7.0': + resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} + + '@ethersproject/abstract-provider@5.7.0': + resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + + '@ethersproject/abstract-signer@5.7.0': + resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + + '@ethersproject/address@5.7.0': + resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + + '@ethersproject/base64@5.7.0': + resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + + '@ethersproject/basex@5.7.0': + resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + + '@ethersproject/bignumber@5.7.0': + resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + + '@ethersproject/bytes@5.7.0': + resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + + '@ethersproject/constants@5.7.0': + resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + + '@ethersproject/contracts@5.7.0': + resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} + + '@ethersproject/hash@5.7.0': + resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + + '@ethersproject/hdnode@5.7.0': + resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} + + '@ethersproject/json-wallets@5.7.0': + resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} + + '@ethersproject/keccak256@5.7.0': + resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + + '@ethersproject/logger@5.7.0': + resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} + + '@ethersproject/networks@5.7.1': + resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + + '@ethersproject/pbkdf2@5.7.0': + resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + + '@ethersproject/properties@5.7.0': + resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + + '@ethersproject/providers@5.7.2': + resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} + + '@ethersproject/random@5.7.0': + resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + + '@ethersproject/rlp@5.7.0': + resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + + '@ethersproject/sha2@5.7.0': + resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + + '@ethersproject/signing-key@5.7.0': + resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + + '@ethersproject/solidity@5.7.0': + resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} + + '@ethersproject/strings@5.7.0': + resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + + '@ethersproject/transactions@5.7.0': + resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + + '@ethersproject/units@5.7.0': + resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} + + '@ethersproject/wallet@5.7.0': + resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} + + '@ethersproject/web@5.7.1': + resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + + '@ethersproject/wordlists@5.7.0': + resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.2': + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@metamask/eth-sig-util@4.0.1': + resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} + engines: {node: '>=12.0.0'} + + '@noble/curves@1.2.0': + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + + '@noble/curves@1.3.0': + resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + + '@noble/hashes@1.2.0': + resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} + + '@noble/hashes@1.3.2': + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + + '@noble/hashes@1.3.3': + resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} + engines: {node: '>= 16'} + + '@noble/secp256k1@1.7.1': + resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nomicfoundation/edr-darwin-arm64@0.6.4': + resolution: {integrity: sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-darwin-x64@0.6.4': + resolution: {integrity: sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-arm64-gnu@0.6.4': + resolution: {integrity: sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-arm64-musl@0.6.4': + resolution: {integrity: sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-x64-gnu@0.6.4': + resolution: {integrity: sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-linux-x64-musl@0.6.4': + resolution: {integrity: sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr-win32-x64-msvc@0.6.4': + resolution: {integrity: sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw==} + engines: {node: '>= 18'} + + '@nomicfoundation/edr@0.6.4': + resolution: {integrity: sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw==} + engines: {node: '>= 18'} + + '@nomicfoundation/ethereumjs-common@4.0.4': + resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} + + '@nomicfoundation/ethereumjs-rlp@5.0.4': + resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} + engines: {node: '>=18'} + hasBin: true + + '@nomicfoundation/ethereumjs-tx@5.0.4': + resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/ethereumjs-util@9.0.4': + resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/hardhat-chai-matchers@2.0.6': + resolution: {integrity: sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + + '@nomicfoundation/hardhat-ethers@3.0.5': + resolution: {integrity: sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw==} + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + + '@nomicfoundation/hardhat-network-helpers@1.0.10': + resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} + peerDependencies: + hardhat: ^2.9.5 + + '@nomicfoundation/hardhat-toolbox@3.0.0': + resolution: {integrity: sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==} + peerDependencies: + '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-network-helpers': ^1.0.0 + '@nomicfoundation/hardhat-verify': ^1.0.0 + '@typechain/ethers-v6': ^0.4.0 + '@typechain/hardhat': ^8.0.0 + '@types/chai': ^4.2.0 + '@types/mocha': '>=9.1.0' + '@types/node': '>=12.0.0' + chai: ^4.2.0 + ethers: ^6.4.0 + hardhat: ^2.11.0 + hardhat-gas-reporter: ^1.0.8 + solidity-coverage: ^0.8.1 + ts-node: '>=8.0.0' + typechain: ^8.2.0 + typescript: '>=4.5.0' + + '@nomicfoundation/hardhat-verify@1.1.1': + resolution: {integrity: sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==} + peerDependencies: + hardhat: ^2.0.4 + + '@nomicfoundation/slang-darwin-arm64@0.17.0': + resolution: {integrity: sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-darwin-x64@0.17.0': + resolution: {integrity: sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-arm64-gnu@0.17.0': + resolution: {integrity: sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-arm64-musl@0.17.0': + resolution: {integrity: sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-x64-gnu@0.17.0': + resolution: {integrity: sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-linux-x64-musl@0.17.0': + resolution: {integrity: sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-arm64-msvc@0.17.0': + resolution: {integrity: sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-ia32-msvc@0.17.0': + resolution: {integrity: sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang-win32-x64-msvc@0.17.0': + resolution: {integrity: sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA==} + engines: {node: '>= 10'} + + '@nomicfoundation/slang@0.17.0': + resolution: {integrity: sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ==} + engines: {node: '>= 10'} + + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': + resolution: {integrity: sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1': + resolution: {integrity: sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1': + resolution: {integrity: sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1': + resolution: {integrity: sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1': + resolution: {integrity: sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1': + resolution: {integrity: sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1': + resolution: {integrity: sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1': + resolution: {integrity: sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1': + resolution: {integrity: sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1': + resolution: {integrity: sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nomicfoundation/solidity-analyzer@0.1.1': + resolution: {integrity: sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==} + engines: {node: '>= 12'} + + '@npmcli/fs@1.1.1': + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} + + '@npmcli/move-file@1.1.2': + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + deprecated: This functionality has been moved to @npmcli/fs + + '@openzeppelin/contracts-upgradeable@5.0.2': + resolution: {integrity: sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==} + peerDependencies: + '@openzeppelin/contracts': 5.0.2 + + '@openzeppelin/contracts@5.0.2': + resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==} + + '@openzeppelin/defender-sdk-base-client@1.15.0': + resolution: {integrity: sha512-nuf/xegMIuKCO0hMrxI1KQKTzQw1iCl/9kew2nJM9MrFIohhfEXItc5rbJRoV/jehmK/Jhi9ATF9OHH09StEsQ==} + + '@openzeppelin/defender-sdk-deploy-client@1.15.0': + resolution: {integrity: sha512-2ODMN4j5pPYWyIOvA/zRQmJ0tJyqi6NV3S/PyvufBXa3oj/MDnVO5bMGSQFH0M2VE3bg+i/rcUb0hdbX9Rtm5Q==} + + '@openzeppelin/defender-sdk-network-client@1.15.0': + resolution: {integrity: sha512-tNynCqFB1XYancq/8yGuj0HCSIyNLSRSuH53Hp2Tl+DpM7W5vIkzSRfvJJxC+8Sld83bVavyNJzTN9xid992Ag==} + + '@openzeppelin/hardhat-upgrades@3.5.0': + resolution: {integrity: sha512-Ju/JnT7NRiOMi5m5Y0dGiz37d8wnjVBep1v5Vr7+6+MFNuQa1yddUEVWhWhoEw4udI3/mYwyw4Sfz3sq7vhicQ==} + hasBin: true + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.0 + '@nomicfoundation/hardhat-verify': ^2.0.0 + ethers: ^6.6.0 + hardhat: ^2.0.2 + peerDependenciesMeta: + '@nomicfoundation/hardhat-verify': + optional: true + + '@openzeppelin/upgrades-core@1.40.0': + resolution: {integrity: sha512-4bPSXdEqHsNRL5T1ybPLneWGYjzGl6XWGWkv7aUoFFgz8mOdarstRBX1Wi4XJFw6IeHPUI7mMSQr2jdz8Y2ypQ==} + hasBin: true + + '@scure/base@1.1.5': + resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==} + + '@scure/bip32@1.1.5': + resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} + + '@scure/bip32@1.3.3': + resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + + '@scure/bip39@1.1.1': + resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} + + '@scure/bip39@1.2.2': + resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + + '@sentry/core@5.30.0': + resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} + engines: {node: '>=6'} + + '@sentry/hub@5.30.0': + resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} + engines: {node: '>=6'} + + '@sentry/minimal@5.30.0': + resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} + engines: {node: '>=6'} + + '@sentry/node@5.30.0': + resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} + engines: {node: '>=6'} + + '@sentry/tracing@5.30.0': + resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} + engines: {node: '>=6'} + + '@sentry/types@5.30.0': + resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} + engines: {node: '>=6'} + + '@sentry/utils@5.30.0': + resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} + engines: {node: '>=6'} + + '@smithy/types@3.6.0': + resolution: {integrity: sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w==} + engines: {node: '>=16.0.0'} + + '@solidity-parser/parser@0.14.5': + resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} + + '@solidity-parser/parser@0.16.2': + resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} + + '@solidity-parser/parser@0.17.0': + resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} + + '@solidity-parser/parser@0.18.0': + resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} + + '@tootallnate/once@1.1.2': + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + + '@trivago/prettier-plugin-sort-imports@4.3.0': + resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} + peerDependencies: + '@vue/compiler-sfc': 3.x + prettier: 2.x - 3.x + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + + '@tsconfig/node10@1.0.9': + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@typechain/ethers-v6@0.4.3': + resolution: {integrity: sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==} + peerDependencies: + ethers: 6.x + typechain: ^8.3.1 + typescript: '>=4.7.0' + + '@typechain/hardhat@8.0.3': + resolution: {integrity: sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==} + peerDependencies: + '@typechain/ethers-v6': ^0.4.3 + ethers: ^6.1.0 + hardhat: ^2.9.9 + typechain: ^8.3.1 + + '@types/bn.js@4.11.6': + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + + '@types/bn.js@5.1.5': + resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} + + '@types/chai-as-promised@7.1.8': + resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + + '@types/chai@4.3.12': + resolution: {integrity: sha512-zNKDHG/1yxm8Il6uCCVsm+dRdEsJlFoDu73X17y09bId6UwoYww+vFBsAcRzl8knM1sab3Dp1VRikFQwDOtDDw==} + + '@types/concat-stream@1.6.1': + resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} + + '@types/form-data@0.0.33': + resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} + + '@types/fs-extra@9.0.13': + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + + '@types/glob-to-regexp@0.4.4': + resolution: {integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/keccak@3.0.5': + resolution: {integrity: sha512-Mvu4StIJ9KyfPXDVRv3h0fWNBAjHPBQZ8EPcxhqA8FG6pLzxtytVXU5owB6J2/8xZ+ZspWTXJEUjAHt0pk0I1Q==} + + '@types/lru-cache@5.1.1': + resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/mkdirp@0.5.2': + resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} + + '@types/mocha@10.0.6': + resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + + '@types/node@10.17.60': + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + + '@types/node@18.15.13': + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + + '@types/node@18.19.59': + resolution: {integrity: sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==} + + '@types/node@8.10.66': + resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} + + '@types/pbkdf2@3.1.2': + resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/qs@6.9.12': + resolution: {integrity: sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==} + + '@types/resolve@0.0.8': + resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} + + '@types/secp256k1@4.0.6': + resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@typescript-eslint/eslint-plugin@5.62.0': + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@5.62.0': + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/type-utils@5.62.0': + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + abbrev@1.0.9: + resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adm-zip@0.4.16: + resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} + engines: {node: '>=0.3.0'} + + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + + aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + amazon-cognito-identity-js@6.3.12: + resolution: {integrity: sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==} + + amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + antlr4@4.13.1: + resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} + engines: {node: '>=16'} + + antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-back@3.1.0: + resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} + engines: {node: '>=6'} + + array-back@4.0.2: + resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} + engines: {node: '>=8'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + + async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@0.21.4: + resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + + axios@1.6.7: + resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} + + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + + bigint-buffer@1.1.5: + resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} + engines: {node: '>= 10.0.0'} + + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + bn.js@4.11.6: + resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} + + bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + + bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + + boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cacache@15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + + cbor@8.1.0: + resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} + engines: {node: '>=12.19'} + + cbor@9.0.2: + resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} + engines: {node: '>=16'} + + chai-as-promised@7.1.1: + resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} + peerDependencies: + chai: '>= 2.1.2 < 5' + + chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + + cli-table3@0.5.1: + resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} + engines: {node: '>=6'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + + command-line-args@5.2.1: + resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} + engines: {node: '>=4.0.0'} + + command-line-usage@6.1.3: + resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} + engines: {node: '>=8.0.0'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + + death@1.1.0: + resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + + difflib@0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + + elliptic@6.5.5: + resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@1.8.1: + resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} + engines: {node: '>=0.12.0'} + hasBin: true + + eslint-config-prettier@8.10.0: + resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@2.7.3: + resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} + engines: {node: '>=0.10.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@1.9.3: + resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} + engines: {node: '>=0.10.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eth-gas-reporter@0.2.27: + resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==} + peerDependencies: + '@codechecks/client': ^0.1.0 + peerDependenciesMeta: + '@codechecks/client': + optional: true + + ethereum-bloom-filters@1.0.10: + resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} + + ethereum-cryptography@0.1.3: + resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + + ethereum-cryptography@1.2.0: + resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} + + ethereum-cryptography@2.1.3: + resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + + ethereumjs-abi@0.6.8: + resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + + ethereumjs-util@6.2.1: + resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + + ethereumjs-util@7.1.5: + resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} + engines: {node: '>=10.0.0'} + + ethers@5.7.2: + resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} + + ethers@6.11.1: + resolution: {integrity: sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==} + engines: {node: '>=14.0.0'} + + ethjs-unit@0.1.6: + resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} + engines: {node: '>=6.5.0', npm: '>=3'} + + ethjs-util@0.1.6: + resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} + engines: {node: '>=6.5.0', npm: '>=3'} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + extra-bigint@1.2.0: + resolution: {integrity: sha512-F9T/pcT5xPZTjlFMKGCZgBY2/jKqEPxXHT4kLSwsa7gp7D05nQq8z9NzRTzVy5Z4AOO1E/iD9r9OBz4csGD7nw==} + + fast-base64-decode@1.0.0: + resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fetch-mock@11.1.5: + resolution: {integrity: sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==} + engines: {node: '>=8.0.0'} + peerDependencies: + node-fetch: '*' + peerDependenciesMeta: + node-fetch: + optional: true + + fhevm-core-contracts@0.1.0-2: + resolution: {integrity: sha512-lTUodggGV4+pZVFRKRb22t3rWyfR8iFZLgNxRBozgAEUSsIDe16PI9vn8PkfJzJJdOlPk9XsTY6/s1pACDbwfA==} + + fhevm@0.6.0-0: + resolution: {integrity: sha512-Gvd7a5T7JTU3OFHy2eRrvRTTmXWwSalSSsBdE0X0C0nTnTow5sYsQYkQqIZcYZNpZq1dCcoCgp/gYbeNDHUDNw==} + engines: {node: '>=20.0.0'} + + fhevmjs@0.6.0-4: + resolution: {integrity: sha512-gPnEHnkAwoJivP+K1KtOx7ZeBpZGtQW1QaAVC1zxDtMWQKCcqJMmNQOt0ur/2buw6WE4VfDIIWXneZ1hHCzLHQ==} + engines: {node: '>=20'} + hasBin: true + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-replace@3.0.0: + resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} + engines: {node: '>=4.0.0'} + + find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + fmix@0.1.0: + resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} + + follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + fp-ts@1.19.3: + resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-readdir-recursive@1.1.0: + resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-port@3.2.0: + resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} + engines: {node: '>=4'} + + ghost-testrpc@0.0.2: + resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} + hasBin: true + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@5.0.15: + resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + + glob@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + + glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globby@10.0.2: + resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + hardhat-deploy@0.11.45: + resolution: {integrity: sha512-aC8UNaq3JcORnEUIwV945iJuvBwi65tjHVDU3v6mOcqik7WAzHVCJ7cwmkkipsHrWysrB5YvGF1q9S1vIph83w==} + + hardhat-gas-reporter@1.0.10: + resolution: {integrity: sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==} + peerDependencies: + hardhat: ^2.0.2 + + hardhat-ignore-warnings@0.2.11: + resolution: {integrity: sha512-+nHnRbP6COFZaXE7HAY7TZNE3au5vHe5dkcnyq0XaP07ikT2fJ3NhFY0vn7Deh4Qbz0Z/9Xpnj2ki6Ktgk61pg==} + + hardhat-preprocessor@0.1.5: + resolution: {integrity: sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g==} + peerDependencies: + hardhat: ^2.0.5 + + hardhat@2.22.14: + resolution: {integrity: sha512-sD8vHtS9l5QQVHzyPPe3auwZDJyZ0fG3Z9YENVa4oOqVEefCuHcPzdU736rei3zUKTqkX0zPIHkSMHpu02Fq1A==} + hasBin: true + peerDependencies: + ts-node: '*' + typescript: '*' + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + + has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + http-basic@8.1.3: + resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} + engines: {node: '>=6.0.0'} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + + http-response-object@3.0.2: + resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + immutable@4.3.5: + resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imul@1.0.1: + resolution: {integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==} + engines: {node: '>=0.10.0'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + + io-ts@1.10.4: + resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hex-prefixed@1.0.0: + resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} + engines: {node: '>=6.5.0', npm: '>=3'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-subset@0.1.1: + resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic-unfetch@3.1.0: + resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} + + javascript-natural-sort@0.7.1: + resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + + js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stream-stringify@3.1.6: + resolution: {integrity: sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==} + engines: {node: '>=7.10.1'} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonschema@1.4.1: + resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} + + keccak@3.0.4: + resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} + engines: {node: '>=10.0.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru_map@0.3.3: + resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + make-fetch-happen@9.1.0: + resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} + engines: {node: '>= 10'} + + markdown-table@1.1.3: + resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} + + match-all@1.2.6: + resolution: {integrity: sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micro-ftch@0.3.1: + resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@1.4.1: + resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} + engines: {node: '>=8'} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mnemonist@0.38.5: + resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + + mocha@10.3.0: + resolution: {integrity: sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==} + engines: {node: '>= 14.0.0'} + hasBin: true + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + murmur-128@0.2.1: + resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} + + napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-abi@3.71.0: + resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==} + engines: {node: '>=10'} + + node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-emoji@1.11.0: + resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build@4.8.0: + resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} + hasBin: true + + node-gyp@8.4.1: + resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} + engines: {node: '>= 10.12.0'} + hasBin: true + + node-interval-tree@2.1.2: + resolution: {integrity: sha512-bJ9zMDuNGzVQg1xv0bCPzyEDxHgbrx7/xGj6CDokvizZZmastPsOh0JJLuY8wA5q2SfX1TLNMk7XNV8WxbGxzA==} + engines: {node: '>= 14.0.0'} + + node-tfhe@0.8.6: + resolution: {integrity: sha512-u9WHiD/vTQ/FIph+52l/jyKzyDh/vLnyw50oSdz0eb1CTs2lqbiA8l8MNxgMkBP1zDadR0qzg37VCt3UkoC2ig==} + + node-tkms@0.9.0-rc3: + resolution: {integrity: sha512-Jr3faNAudjBO2Up+Gc3QPF7Dq07fDR/n0NKCHGtS69qLKnoqqaKxGULdKg3gpbtdx0wnj/GaQjvprUIgnIm7yQ==} + + nofilter@3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + + nopt@3.0.6: + resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} + hasBin: true + + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + number-to-bn@1.7.0: + resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} + engines: {node: '>=6.5.0', npm: '>=3'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + + optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + + ordinal@1.0.3: + resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + p-limit@1.3.0: + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-try@1.0.0: + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-cache-control@1.0.1: + resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + prebuild-install@7.1.2: + resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} + engines: {node: '>=10'} + hasBin: true + + prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-solidity@1.3.1: + resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} + engines: {node: '>=16'} + peerDependencies: + prettier: '>=2.3.0' + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.12.0: + resolution: {integrity: sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==} + engines: {node: '>=0.6'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + + recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + + reduce-flatten@2.0.0: + resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} + engines: {node: '>=6'} + + regexparam@3.0.0: + resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} + engines: {node: '>=8'} + + req-cwd@2.0.0: + resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} + engines: {node: '>=4'} + + req-from@2.0.0: + resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} + engines: {node: '>=4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@3.0.0: + resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} + engines: {node: '>=4'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.1.7: + resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} + + resolve@1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rimraf@4.4.1: + resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} + engines: {node: '>=14'} + hasBin: true + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + rlp@2.2.7: + resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sc-istanbul@0.4.6: + resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} + hasBin: true + + scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + + secp256k1@4.0.3: + resolution: {integrity: sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==} + engines: {node: '>=10.0.0'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + sha1@1.1.1: + resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} + + sha3@2.1.4: + resolution: {integrity: sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==} + + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@6.2.1: + resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} + engines: {node: '>= 10'} + + socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + solc@0.8.26: + resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} + engines: {node: '>=10.0.0'} + hasBin: true + + solhint-plugin-prettier@0.0.5: + resolution: {integrity: sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==} + peerDependencies: + prettier: ^1.15.0 || ^2.0.0 + prettier-plugin-solidity: ^1.0.0-alpha.14 + + solhint@3.6.2: + resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} + hasBin: true + + solidity-ast@0.4.59: + resolution: {integrity: sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g==} + + solidity-comments-darwin-arm64@0.0.2: + resolution: {integrity: sha512-HidWkVLSh7v+Vu0CA7oI21GWP/ZY7ro8g8OmIxE8oTqyMwgMbE8F1yc58Sj682Hj199HCZsjmtn1BE4PCbLiGA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + solidity-comments-darwin-x64@0.0.2: + resolution: {integrity: sha512-Zjs0Ruz6faBTPT6fBecUt6qh4CdloT8Bwoc0+qxRoTn9UhYscmbPQkUgQEbS0FQPysYqVzzxJB4h1Ofbf4wwtA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + solidity-comments-extractor@0.0.8: + resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} + + solidity-comments-freebsd-x64@0.0.2: + resolution: {integrity: sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + solidity-comments-linux-arm64-gnu@0.0.2: + resolution: {integrity: sha512-spkb0MZZnmrP+Wtq4UxP+nyPAVRe82idOjqndolcNR0S9Xvu4ebwq+LvF4HiUgjTDmeiqYiFZQ8T9KGdLSIoIg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + solidity-comments-linux-arm64-musl@0.0.2: + resolution: {integrity: sha512-guCDbHArcjE+JDXYkxx5RZzY1YF6OnAKCo+sTC5fstyW/KGKaQJNPyBNWuwYsQiaEHpvhW1ha537IvlGek8GqA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + solidity-comments-linux-x64-gnu@0.0.2: + resolution: {integrity: sha512-zIqLehBK/g7tvrFmQljrfZXfkEeLt2v6wbe+uFu6kH/qAHZa7ybt8Vc0wYcmjo2U0PeBm15d79ee3AkwbIjFdQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solidity-comments-linux-x64-musl@0.0.2: + resolution: {integrity: sha512-R9FeDloVlFGTaVkOlELDVC7+1Tjx5WBPI5L8r0AGOPHK3+jOcRh6sKYpI+VskSPDc3vOO46INkpDgUXrKydlIw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solidity-comments-win32-arm64-msvc@0.0.2: + resolution: {integrity: sha512-QnWJoCQcJj+rnutULOihN9bixOtYWDdF5Rfz9fpHejL1BtNjdLW1om55XNVHGAHPqBxV4aeQQ6OirKnp9zKsug==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + solidity-comments-win32-ia32-msvc@0.0.2: + resolution: {integrity: sha512-vUg4nADtm/NcOtlIymG23NWJUSuMsvX15nU7ynhGBsdKtt8xhdP3C/zA6vjDk8Jg+FXGQL6IHVQ++g/7rSQi0w==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + solidity-comments-win32-x64-msvc@0.0.2: + resolution: {integrity: sha512-36j+KUF4V/y0t3qatHm/LF5sCUCBx2UndxE1kq5bOzh/s+nQgatuyB+Pd5BfuPQHdWu2KaExYe20FlAa6NL7+Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + solidity-comments@0.0.2: + resolution: {integrity: sha512-G+aK6qtyUfkn1guS8uzqUeua1dURwPlcOjoTYW/TwmXAcE7z/1+oGCfZUdMSe4ZMKklNbVZNiG5ibnF8gkkFfw==} + engines: {node: '>= 12'} + + solidity-coverage@0.8.12: + resolution: {integrity: sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==} + hasBin: true + peerDependencies: + hardhat: ^2.11.0 + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.2.0: + resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} + engines: {node: '>=0.8.0'} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + sqlite3@5.1.7: + resolution: {integrity: sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==} + + ssri@8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + + stacktrace-parser@0.1.10: + resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} + engines: {node: '>=6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + string-format@2.0.0: + resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} + + string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-hex-prefix@1.0.0: + resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} + engines: {node: '>=6.5.0', npm: '>=3'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + sync-request@6.1.0: + resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} + engines: {node: '>=8.0.0'} + + sync-rpc@1.3.6: + resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} + + table-layout@1.0.2: + resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} + engines: {node: '>=8.0.0'} + + table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + + tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + tfhe@0.8.6: + resolution: {integrity: sha512-Mxa6ywC4fAayHK0xBPJfrVUt4Tt5+ozQyVQcAlj3gK1i5rJI/pcwCDvf27Xxtkb0fMyRYgKDwrETVfC51r1Fcw==} + + then-request@6.0.2: + resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} + engines: {node: '>=6.0.0'} + + tkms@0.9.0-rc3: + resolution: {integrity: sha512-7ynaHiFnXS9Xok62vsi2GGeTUxmb1Ao7I5k9akE8lEQ5M9FERmaGLF3TapDLGsYMDz7Km7dFeTfrsjCg38OC/w==} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-command-line-args@2.5.1: + resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} + hasBin: true + + ts-essentials@1.0.4: + resolution: {integrity: sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==} + + ts-essentials@7.0.3: + resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} + peerDependencies: + typescript: '>=3.7.0' + + ts-generator@0.1.1: + resolution: {integrity: sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==} + hasBin: true + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + + tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + + tsort@0.0.1: + resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + + type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} -packages: + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + typechain@8.3.2: + resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} + hasBin: true + peerDependencies: + typescript: '>=4.3.0' + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + + typical@4.0.0: + resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} + engines: {node: '>=8'} + + typical@5.2.0: + resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} + engines: {node: '>=8'} + + uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@5.28.3: + resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==} + engines: {node: '>=14.0'} + + undici@6.20.1: + resolution: {integrity: sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==} + engines: {node: '>=18.17'} + + unfetch@4.2.0: + resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} + + unique-filename@1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + + unique-slug@2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + web3-errors@1.3.0: + resolution: {integrity: sha512-j5JkAKCtuVMbY3F5PYXBqg1vWrtF4jcyyMY1rlw8a4PV67AkqlepjGgpzWJZd56Mt+TvHy6DA1F/3Id8LatDSQ==} + engines: {node: '>=14', npm: '>=6.12.0'} + + web3-types@1.8.1: + resolution: {integrity: sha512-isspsvQbBJFUkJYz2Badb7dz/BrLLLpOop/WmnL5InyYMr7kYYc8038NYO7Vkp1M7Bupa/wg+yALvBm7EGbyoQ==} + engines: {node: '>=14', npm: '>=6.12.0'} + + web3-utils@1.10.4: + resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} + engines: {node: '>=8.0.0'} + + web3-validator@2.0.6: + resolution: {integrity: sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==} + engines: {node: '>=14', npm: '>=6.12.0'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - dev: true - /@adraffy/ens-normalize@1.10.1: - resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - dev: true + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - /@babel/code-frame@7.23.5: - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} - engines: {node: '>=6.9.0'} + wordwrapjs@4.0.1: + resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} + engines: {node: '>=8.0.0'} + + workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zksync-web3@0.14.4: + resolution: {integrity: sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg==} + deprecated: This package has been deprecated in favor of zksync-ethers@5.0.0 + peerDependencies: + ethers: ^5.7.0 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + +snapshots: + + '@aashutoshrathi/word-wrap@1.2.6': {} + + '@adraffy/ens-normalize@1.10.1': {} + + '@aws-crypto/sha256-js@1.2.2': + dependencies: + '@aws-crypto/util': 1.2.2 + '@aws-sdk/types': 3.679.0 + tslib: 1.14.1 + + '@aws-crypto/util@1.2.2': + dependencies: + '@aws-sdk/types': 3.679.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + + '@aws-sdk/types@3.679.0': + dependencies: + '@smithy/types': 3.6.0 + tslib: 2.8.0 + + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.4.0 + + '@babel/code-frame@7.23.5': dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 - dev: true - /@babel/generator@7.17.7: - resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} - engines: {node: '>=6.9.0'} + '@babel/generator@7.17.7': dependencies: '@babel/types': 7.17.0 jsesc: 2.5.2 source-map: 0.5.7 - dev: true - /@babel/generator@7.23.6: - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} - engines: {node: '>=6.9.0'} + '@babel/generator@7.23.6': dependencies: '@babel/types': 7.24.0 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - dev: true - /@babel/helper-environment-visitor@7.22.20: - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-environment-visitor@7.22.20': {} - /@babel/helper-function-name@7.23.0: - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} + '@babel/helper-function-name@7.23.0': dependencies: '@babel/template': 7.24.0 '@babel/types': 7.24.0 - dev: true - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} + '@babel/helper-hoist-variables@7.22.5': dependencies: '@babel/types': 7.24.0 - dev: true - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.22.6': dependencies: '@babel/types': 7.24.0 - dev: true - /@babel/helper-string-parser@7.23.4: - resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-string-parser@7.23.4': {} - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-validator-identifier@7.22.20': {} - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} + '@babel/highlight@7.23.4': dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true - /@babel/parser@7.24.0: - resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} - engines: {node: '>=6.0.0'} - hasBin: true + '@babel/parser@7.24.0': dependencies: '@babel/types': 7.17.0 - dev: true - /@babel/template@7.24.0: - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} - engines: {node: '>=6.9.0'} + '@babel/template@7.24.0': dependencies: '@babel/code-frame': 7.23.5 '@babel/parser': 7.24.0 '@babel/types': 7.24.0 - dev: true - /@babel/traverse@7.23.2: - resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} - engines: {node: '>=6.9.0'} + '@babel/traverse@7.23.2': dependencies: '@babel/code-frame': 7.23.5 '@babel/generator': 7.23.6 @@ -248,50 +3465,30 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/types@7.17.0: - resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} - engines: {node: '>=6.9.0'} + '@babel/types@7.17.0': dependencies: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} + '@babel/types@7.24.0': dependencies: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - dev: true - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true + '@eslint-community/regexpp@4.10.0': {} - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 debug: 4.3.4(supports-color@8.1.1) @@ -304,30 +3501,18 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: true - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + '@eslint/js@8.57.0': {} - /@ethereumjs/rlp@4.0.1: - resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} - engines: {node: '>=14'} - hasBin: true - dev: true + '@ethereumjs/rlp@4.0.1': {} - /@ethereumjs/util@8.1.0: - resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} - engines: {node: '>=14'} + '@ethereumjs/util@8.1.0': dependencies: '@ethereumjs/rlp': 4.0.1 ethereum-cryptography: 2.1.3 micro-ftch: 0.3.1 - dev: true - /@ethersproject/abi@5.7.0: - resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} + '@ethersproject/abi@5.7.0': dependencies: '@ethersproject/address': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -338,10 +3523,8 @@ packages: '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - dev: true - /@ethersproject/abstract-provider@5.7.0: - resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + '@ethersproject/abstract-provider@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -350,63 +3533,47 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/transactions': 5.7.0 '@ethersproject/web': 5.7.1 - dev: true - /@ethersproject/abstract-signer@5.7.0: - resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + '@ethersproject/abstract-signer@5.7.0': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 - dev: true - /@ethersproject/address@5.7.0: - resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + '@ethersproject/address@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/keccak256': 5.7.0 '@ethersproject/logger': 5.7.0 '@ethersproject/rlp': 5.7.0 - dev: true - /@ethersproject/base64@5.7.0: - resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + '@ethersproject/base64@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 - dev: true - /@ethersproject/basex@5.7.0: - resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + '@ethersproject/basex@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/properties': 5.7.0 - dev: true - /@ethersproject/bignumber@5.7.0: - resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + '@ethersproject/bignumber@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 bn.js: 5.2.1 - dev: true - /@ethersproject/bytes@5.7.0: - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + '@ethersproject/bytes@5.7.0': dependencies: '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/constants@5.7.0: - resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + '@ethersproject/constants@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 - dev: true - /@ethersproject/contracts@5.7.0: - resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} + '@ethersproject/contracts@5.7.0': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -418,10 +3585,8 @@ packages: '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 '@ethersproject/transactions': 5.7.0 - dev: true - /@ethersproject/hash@5.7.0: - resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + '@ethersproject/hash@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.7.0 @@ -432,10 +3597,8 @@ packages: '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - dev: true - /@ethersproject/hdnode@5.7.0: - resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} + '@ethersproject/hdnode@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/basex': 5.7.0 @@ -449,10 +3612,8 @@ packages: '@ethersproject/strings': 5.7.0 '@ethersproject/transactions': 5.7.0 '@ethersproject/wordlists': 5.7.0 - dev: true - /@ethersproject/json-wallets@5.7.0: - resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} + '@ethersproject/json-wallets@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.7.0 @@ -467,40 +3628,28 @@ packages: '@ethersproject/transactions': 5.7.0 aes-js: 3.0.0 scrypt-js: 3.0.1 - dev: true - /@ethersproject/keccak256@5.7.0: - resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + '@ethersproject/keccak256@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 js-sha3: 0.8.0 - dev: true - /@ethersproject/logger@5.7.0: - resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} - dev: true + '@ethersproject/logger@5.7.0': {} - /@ethersproject/networks@5.7.1: - resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + '@ethersproject/networks@5.7.1': dependencies: '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/pbkdf2@5.7.0: - resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + '@ethersproject/pbkdf2@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/sha2': 5.7.0 - dev: true - /@ethersproject/properties@5.7.0: - resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + '@ethersproject/properties@5.7.0': dependencies: '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/providers@5.7.2: - resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} + '@ethersproject/providers@5.7.2': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -525,32 +3674,24 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true - /@ethersproject/random@5.7.0: - resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + '@ethersproject/random@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/rlp@5.7.0: - resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + '@ethersproject/rlp@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/sha2@5.7.0: - resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + '@ethersproject/sha2@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 hash.js: 1.1.7 - dev: true - /@ethersproject/signing-key@5.7.0: - resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + '@ethersproject/signing-key@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 @@ -558,10 +3699,8 @@ packages: bn.js: 5.2.1 elliptic: 6.5.4 hash.js: 1.1.7 - dev: true - /@ethersproject/solidity@5.7.0: - resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} + '@ethersproject/solidity@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -569,18 +3708,14 @@ packages: '@ethersproject/logger': 5.7.0 '@ethersproject/sha2': 5.7.0 '@ethersproject/strings': 5.7.0 - dev: true - /@ethersproject/strings@5.7.0: - resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + '@ethersproject/strings@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/constants': 5.7.0 '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/transactions@5.7.0: - resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + '@ethersproject/transactions@5.7.0': dependencies: '@ethersproject/address': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -591,18 +3726,14 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/rlp': 5.7.0 '@ethersproject/signing-key': 5.7.0 - dev: true - /@ethersproject/units@5.7.0: - resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} + '@ethersproject/units@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/constants': 5.7.0 '@ethersproject/logger': 5.7.0 - dev: true - /@ethersproject/wallet@5.7.0: - resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} + '@ethersproject/wallet@5.7.0': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -619,483 +3750,263 @@ packages: '@ethersproject/signing-key': 5.7.0 '@ethersproject/transactions': 5.7.0 '@ethersproject/wordlists': 5.7.0 - dev: true - /@ethersproject/web@5.7.1: - resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + '@ethersproject/web@5.7.1': dependencies: '@ethersproject/base64': 5.7.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - dev: true - /@ethersproject/wordlists@5.7.0: - resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} + '@ethersproject/wordlists@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/hash': 5.7.0 '@ethersproject/logger': 5.7.0 '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - dev: true - /@fastify/busboy@2.1.1: - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - dev: true + '@fastify/busboy@2.1.1': {} - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} + '@gar/promisify@1.1.3': + optional: true + + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.2 debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color - dev: true - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true + '@humanwhocodes/module-importer@1.0.1': {} - /@humanwhocodes/object-schema@2.0.2: - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - dev: true + '@humanwhocodes/object-schema@2.0.2': {} - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.25 - dev: true - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/resolve-uri@3.1.2': {} - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/set-array@1.2.1': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + '@jridgewell/sourcemap-codec@1.4.15': {} - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@metamask/eth-sig-util@4.0.1: - resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} - engines: {node: '>=12.0.0'} + '@metamask/eth-sig-util@4.0.1': dependencies: ethereumjs-abi: 0.6.8 ethereumjs-util: 6.2.1 ethjs-util: 0.1.6 tweetnacl: 1.0.3 tweetnacl-util: 0.15.1 - dev: true - /@noble/curves@1.2.0: - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + '@noble/curves@1.2.0': dependencies: '@noble/hashes': 1.3.2 - dev: true - /@noble/curves@1.3.0: - resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + '@noble/curves@1.3.0': dependencies: '@noble/hashes': 1.3.3 - dev: true - /@noble/hashes@1.2.0: - resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} - dev: true + '@noble/hashes@1.2.0': {} - /@noble/hashes@1.3.2: - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - dev: true + '@noble/hashes@1.3.2': {} - /@noble/hashes@1.3.3: - resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} - engines: {node: '>= 16'} - dev: true + '@noble/hashes@1.3.3': {} - /@noble/secp256k1@1.7.1: - resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} - dev: true + '@noble/secp256k1@1.7.1': {} - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - dev: true - - /@nomicfoundation/edr-darwin-arm64@0.2.1: - resolution: {integrity: sha512-aMYaRaZVQ/TmyNJIoXf1bU4k0zfinaL9Sy1day4yGlL6eiQPFfRGj9W6TZaZIoYG0XTx/mQWD7dkXJ7LdrleJA==} - engines: {node: '>= 18'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@nomicfoundation/edr-darwin-x64@0.2.1: - resolution: {integrity: sha512-ma0SLcjHm5L3nPHcKFJB0jv/gKGSKaxr5Z65rurX/eaYUQJ7YGMsb8er9bSCo9rjzOtxf4FoPj3grL3zGpOj8A==} - engines: {node: '>= 18'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-darwin-arm64@0.6.4': {} - /@nomicfoundation/edr-linux-arm64-gnu@0.2.1: - resolution: {integrity: sha512-NX3G4pBhRitWrjSGY3HTyCq3wKSm5YqrKVOCNQGl9/jcjSovqxlgzFMiTx4YZCzGntfJ/1om9AI84OWxYJjoDw==} - engines: {node: '>= 18'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-darwin-x64@0.6.4': {} - /@nomicfoundation/edr-linux-arm64-musl@0.2.1: - resolution: {integrity: sha512-gdQ3QHkt9XRkdtOGQ8fMwS11MXdjLeZgLrqoial4V4qtMaamIMMhVczK+VEvUhD8p7G4BVmp6kmkvcsthmndmw==} - engines: {node: '>= 18'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-linux-arm64-gnu@0.6.4': {} - /@nomicfoundation/edr-linux-x64-gnu@0.2.1: - resolution: {integrity: sha512-OqabFY37vji6mYbLD9CvG28lja68czeVw58oWByIhFV3BpBu/cyP1oAbhzk3LieylujabS3Ekpvjw2Tkf0A9RQ==} - engines: {node: '>= 18'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-linux-arm64-musl@0.6.4': {} - /@nomicfoundation/edr-linux-x64-musl@0.2.1: - resolution: {integrity: sha512-vHfFFK2EPISuQUQge+bdjXamb0EUjfl8srYSog1qfiwyLwLeuSbpyyFzDeITAgPpkkFuedTfJW553K0Hipspyg==} - engines: {node: '>= 18'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-linux-x64-gnu@0.6.4': {} - /@nomicfoundation/edr-win32-arm64-msvc@0.2.1: - resolution: {integrity: sha512-K/mui67RCKxghbSyvhvW3rvyVN1pa9M1Q9APUx1PtWjSSdXDFpqEY1NYsv2syb47Ca8ObJwVMF+LvnB6GvhUOQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-linux-x64-musl@0.6.4': {} - /@nomicfoundation/edr-win32-ia32-msvc@0.2.1: - resolution: {integrity: sha512-HHK0mXEtjvfjJrJlqcYgQCy3lZIXS1KNl2GaP8bwEIuEwx++XxXs/ThLjPepM1nhCGICij8IGy7p3KrkzRelsw==} - engines: {node: '>= 18'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr-win32-x64-msvc@0.6.4': {} - /@nomicfoundation/edr-win32-x64-msvc@0.2.1: - resolution: {integrity: sha512-FY4eQJdj1/y8ST0RyQycx63yr+lvdYNnUkzgWf4X+vPH1lOhXae+L2NDcNCQlTDAfQcD6yz0bkBUkLrlJ8pTww==} - engines: {node: '>= 18'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + '@nomicfoundation/edr@0.6.4': + dependencies: + '@nomicfoundation/edr-darwin-arm64': 0.6.4 + '@nomicfoundation/edr-darwin-x64': 0.6.4 + '@nomicfoundation/edr-linux-arm64-gnu': 0.6.4 + '@nomicfoundation/edr-linux-arm64-musl': 0.6.4 + '@nomicfoundation/edr-linux-x64-gnu': 0.6.4 + '@nomicfoundation/edr-linux-x64-musl': 0.6.4 + '@nomicfoundation/edr-win32-x64-msvc': 0.6.4 - /@nomicfoundation/edr@0.2.1: - resolution: {integrity: sha512-Dleau3ItHJh2n85G2J6AIPBoLgu/mOWkmrh26z3VsJE2tp/e00hUk/dqz85ncsVcBYEc6/YOn/DomWu0wSF9tQ==} - engines: {node: '>= 18'} - optionalDependencies: - '@nomicfoundation/edr-darwin-arm64': 0.2.1 - '@nomicfoundation/edr-darwin-x64': 0.2.1 - '@nomicfoundation/edr-linux-arm64-gnu': 0.2.1 - '@nomicfoundation/edr-linux-arm64-musl': 0.2.1 - '@nomicfoundation/edr-linux-x64-gnu': 0.2.1 - '@nomicfoundation/edr-linux-x64-musl': 0.2.1 - '@nomicfoundation/edr-win32-arm64-msvc': 0.2.1 - '@nomicfoundation/edr-win32-ia32-msvc': 0.2.1 - '@nomicfoundation/edr-win32-x64-msvc': 0.2.1 - dev: true - - /@nomicfoundation/ethereumjs-common@4.0.4: - resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} + '@nomicfoundation/ethereumjs-common@4.0.4': dependencies: '@nomicfoundation/ethereumjs-util': 9.0.4 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-rlp@5.0.4: - resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} - engines: {node: '>=18'} - hasBin: true - dev: true + '@nomicfoundation/ethereumjs-rlp@5.0.4': {} - /@nomicfoundation/ethereumjs-tx@5.0.4: - resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true + '@nomicfoundation/ethereumjs-tx@5.0.4': dependencies: '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 ethereum-cryptography: 0.1.3 - dev: true - /@nomicfoundation/ethereumjs-util@9.0.4: - resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true + '@nomicfoundation/ethereumjs-util@9.0.4': dependencies: '@nomicfoundation/ethereumjs-rlp': 5.0.4 ethereum-cryptography: 0.1.3 - dev: true - /@nomicfoundation/hardhat-chai-matchers@2.0.6(@nomicfoundation/hardhat-ethers@3.0.5)(chai@4.4.1)(ethers@6.11.1)(hardhat@2.21.0): - resolution: {integrity: sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==} - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.0 - chai: ^4.2.0 - ethers: ^6.1.0 - hardhat: ^2.9.4 + '@nomicfoundation/hardhat-chai-matchers@2.0.6(@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(chai@4.4.1)(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@6.11.1)(hardhat@2.21.0) + '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) '@types/chai-as-promised': 7.1.8 chai: 4.4.1 chai-as-promised: 7.1.1(chai@4.4.1) deep-eql: 4.1.3 ethers: 6.11.1 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) ordinal: 1.0.3 - dev: true - /@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.21.0): - resolution: {integrity: sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw==} - peerDependencies: - ethers: ^6.1.0 - hardhat: ^2.0.0 + '@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))': dependencies: debug: 4.3.4(supports-color@8.1.1) ethers: 6.11.1 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - dev: true - /@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.21.0): - resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} - peerDependencies: - hardhat: ^2.9.5 + '@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) - dev: true + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) - /@nomicfoundation/hardhat-toolbox@3.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.6)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomicfoundation/hardhat-network-helpers@1.0.10)(@nomicfoundation/hardhat-verify@1.1.1)(@typechain/ethers-v6@0.4.3)(@typechain/hardhat@8.0.3)(@types/chai@4.3.12)(@types/mocha@10.0.6)(@types/node@18.19.23)(chai@4.4.1)(ethers@6.11.1)(hardhat-gas-reporter@1.0.10)(hardhat@2.21.0)(solidity-coverage@0.8.6)(ts-node@10.9.2)(typechain@8.3.2)(typescript@5.4.2): - resolution: {integrity: sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==} - peerDependencies: - '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 - '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-network-helpers': ^1.0.0 - '@nomicfoundation/hardhat-verify': ^1.0.0 - '@typechain/ethers-v6': ^0.4.0 - '@typechain/hardhat': ^8.0.0 - '@types/chai': ^4.2.0 - '@types/mocha': '>=9.1.0' - '@types/node': '>=12.0.0' - chai: ^4.2.0 - ethers: ^6.4.0 - hardhat: ^2.11.0 - hardhat-gas-reporter: ^1.0.8 - solidity-coverage: ^0.8.1 - ts-node: '>=8.0.0' - typechain: ^8.2.0 - typescript: '>=4.5.0' + '@nomicfoundation/hardhat-toolbox@3.0.0(sziado6kyyqqr3qor4olybdgcq)': dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.0.6(@nomicfoundation/hardhat-ethers@3.0.5)(chai@4.4.1)(ethers@6.11.1)(hardhat@2.21.0) - '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@6.11.1)(hardhat@2.21.0) - '@nomicfoundation/hardhat-network-helpers': 1.0.10(hardhat@2.21.0) - '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.21.0) - '@typechain/ethers-v6': 0.4.3(ethers@6.11.1)(typechain@8.3.2)(typescript@5.4.2) - '@typechain/hardhat': 8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.11.1)(hardhat@2.21.0)(typechain@8.3.2) + '@nomicfoundation/hardhat-chai-matchers': 2.0.6(@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(chai@4.4.1)(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-network-helpers': 1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@typechain/ethers-v6': 0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2) + '@typechain/hardhat': 8.0.3(@typechain/ethers-v6@0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2))(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))(typechain@8.3.2(typescript@5.4.2)) '@types/chai': 4.3.12 '@types/mocha': 10.0.6 - '@types/node': 18.19.23 + '@types/node': 18.19.59 chai: 4.4.1 ethers: 6.11.1 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) - hardhat-gas-reporter: 1.0.10(hardhat@2.21.0) - solidity-coverage: 0.8.6(hardhat@2.21.0) - ts-node: 10.9.2(@types/node@18.19.23)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) + hardhat-gas-reporter: 1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + solidity-coverage: 0.8.12(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + ts-node: 10.9.2(@types/node@18.19.59)(typescript@5.4.2) typechain: 8.3.2(typescript@5.4.2) typescript: 5.4.2 - dev: true - /@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.21.0): - resolution: {integrity: sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==} - peerDependencies: - hardhat: ^2.0.4 + '@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 debug: 4.3.4(supports-color@8.1.1) - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) lodash.clonedeep: 4.5.0 semver: 6.3.1 table: 6.8.1 undici: 5.28.3 transitivePeerDependencies: - supports-color - dev: true - /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1: - resolution: {integrity: sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true + '@nomicfoundation/slang-darwin-arm64@0.17.0': {} + + '@nomicfoundation/slang-darwin-x64@0.17.0': {} + + '@nomicfoundation/slang-linux-arm64-gnu@0.17.0': {} + + '@nomicfoundation/slang-linux-arm64-musl@0.17.0': {} + + '@nomicfoundation/slang-linux-x64-gnu@0.17.0': {} + + '@nomicfoundation/slang-linux-x64-musl@0.17.0': {} + + '@nomicfoundation/slang-win32-arm64-msvc@0.17.0': {} + + '@nomicfoundation/slang-win32-ia32-msvc@0.17.0': {} + + '@nomicfoundation/slang-win32-x64-msvc@0.17.0': {} + + '@nomicfoundation/slang@0.17.0': + dependencies: + '@nomicfoundation/slang-darwin-arm64': 0.17.0 + '@nomicfoundation/slang-darwin-x64': 0.17.0 + '@nomicfoundation/slang-linux-arm64-gnu': 0.17.0 + '@nomicfoundation/slang-linux-arm64-musl': 0.17.0 + '@nomicfoundation/slang-linux-x64-gnu': 0.17.0 + '@nomicfoundation/slang-linux-x64-musl': 0.17.0 + '@nomicfoundation/slang-win32-arm64-msvc': 0.17.0 + '@nomicfoundation/slang-win32-ia32-msvc': 0.17.0 + '@nomicfoundation/slang-win32-x64-msvc': 0.17.0 + + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1: - resolution: {integrity: sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1: - resolution: {integrity: sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1: - resolution: {integrity: sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1: - resolution: {integrity: sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1: - resolution: {integrity: sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1: - resolution: {integrity: sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1: - resolution: {integrity: sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1: - resolution: {integrity: sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1: - resolution: {integrity: sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1': optional: true - /@nomicfoundation/solidity-analyzer@0.1.1: - resolution: {integrity: sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==} - engines: {node: '>= 12'} + '@nomicfoundation/solidity-analyzer@0.1.1': optionalDependencies: '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.1 '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.1 @@ -1107,77 +4018,130 @@ packages: '@nomicfoundation/solidity-analyzer-win32-arm64-msvc': 0.1.1 '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.1 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.1 - dev: true - /@openzeppelin/contracts@5.0.2: - resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==} + '@npmcli/fs@1.1.1': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.6.0 + optional: true - /@scure/base@1.1.5: - resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==} - dev: true + '@npmcli/move-file@1.1.2': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + optional: true - /@scure/bip32@1.1.5: - resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} + '@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2)': + dependencies: + '@openzeppelin/contracts': 5.0.2 + + '@openzeppelin/contracts@5.0.2': {} + + '@openzeppelin/defender-sdk-base-client@1.15.0(encoding@0.1.13)': + dependencies: + amazon-cognito-identity-js: 6.3.12(encoding@0.1.13) + async-retry: 1.3.3 + transitivePeerDependencies: + - encoding + + '@openzeppelin/defender-sdk-deploy-client@1.15.0(debug@4.3.4)(encoding@0.1.13)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.0(encoding@0.1.13) + axios: 1.7.7(debug@4.3.4) + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/defender-sdk-network-client@1.15.0(debug@4.3.4)(encoding@0.1.13)': + dependencies: + '@openzeppelin/defender-sdk-base-client': 1.15.0(encoding@0.1.13) + axios: 1.7.7(debug@4.3.4) + lodash: 4.17.21 + transitivePeerDependencies: + - debug + - encoding + + '@openzeppelin/hardhat-upgrades@3.5.0(@nomicfoundation/hardhat-ethers@3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(@nomicfoundation/hardhat-verify@1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)))(encoding@0.1.13)(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))': + dependencies: + '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + '@openzeppelin/defender-sdk-base-client': 1.15.0(encoding@0.1.13) + '@openzeppelin/defender-sdk-deploy-client': 1.15.0(debug@4.3.4)(encoding@0.1.13) + '@openzeppelin/defender-sdk-network-client': 1.15.0(debug@4.3.4)(encoding@0.1.13) + '@openzeppelin/upgrades-core': 1.40.0 + chalk: 4.1.2 + debug: 4.3.4(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + ethers: 6.11.1 + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) + proper-lockfile: 4.1.2 + undici: 6.20.1 + optionalDependencies: + '@nomicfoundation/hardhat-verify': 1.1.1(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)) + transitivePeerDependencies: + - encoding + - supports-color + + '@openzeppelin/upgrades-core@1.40.0': + dependencies: + '@nomicfoundation/slang': 0.17.0 + cbor: 9.0.2 + chalk: 4.1.2 + compare-versions: 6.1.1 + debug: 4.3.4(supports-color@8.1.1) + ethereumjs-util: 7.1.5 + minimatch: 9.0.5 + minimist: 1.2.8 + proper-lockfile: 4.1.2 + solidity-ast: 0.4.59 + transitivePeerDependencies: + - supports-color + + '@scure/base@1.1.5': {} + + '@scure/bip32@1.1.5': dependencies: '@noble/hashes': 1.2.0 '@noble/secp256k1': 1.7.1 '@scure/base': 1.1.5 - dev: true - /@scure/bip32@1.3.3: - resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + '@scure/bip32@1.3.3': dependencies: '@noble/curves': 1.3.0 '@noble/hashes': 1.3.3 '@scure/base': 1.1.5 - dev: true - /@scure/bip39@1.1.1: - resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} + '@scure/bip39@1.1.1': dependencies: '@noble/hashes': 1.2.0 '@scure/base': 1.1.5 - dev: true - /@scure/bip39@1.2.2: - resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + '@scure/bip39@1.2.2': dependencies: '@noble/hashes': 1.3.3 '@scure/base': 1.1.5 - dev: true - /@sentry/core@5.30.0: - resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} - engines: {node: '>=6'} + '@sentry/core@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/minimal': 5.30.0 '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/hub@5.30.0: - resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} - engines: {node: '>=6'} + '@sentry/hub@5.30.0': dependencies: '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/minimal@5.30.0: - resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} - engines: {node: '>=6'} + '@sentry/minimal@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/types': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/node@5.30.0: - resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} - engines: {node: '>=6'} + '@sentry/node@5.30.0': dependencies: '@sentry/core': 5.30.0 '@sentry/hub': 5.30.0 @@ -1190,60 +4154,42 @@ packages: tslib: 1.14.1 transitivePeerDependencies: - supports-color - dev: true - /@sentry/tracing@5.30.0: - resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} - engines: {node: '>=6'} + '@sentry/tracing@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/minimal': 5.30.0 '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/types@5.30.0: - resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} - engines: {node: '>=6'} - dev: true + '@sentry/types@5.30.0': {} - /@sentry/utils@5.30.0: - resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} - engines: {node: '>=6'} + '@sentry/utils@5.30.0': dependencies: '@sentry/types': 5.30.0 tslib: 1.14.1 - dev: true - /@solidity-parser/parser@0.14.5: - resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} + '@smithy/types@3.6.0': + dependencies: + tslib: 2.8.0 + + '@solidity-parser/parser@0.14.5': dependencies: antlr4ts: 0.5.0-alpha.4 - dev: true - /@solidity-parser/parser@0.16.2: - resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} + '@solidity-parser/parser@0.16.2': dependencies: antlr4ts: 0.5.0-alpha.4 - dev: true - /@solidity-parser/parser@0.17.0: - resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - dev: true + '@solidity-parser/parser@0.17.0': {} - /@solidity-parser/parser@0.18.0: - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - dev: true + '@solidity-parser/parser@0.18.0': {} - /@trivago/prettier-plugin-sort-imports@4.3.0(prettier@2.8.8): - resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} - peerDependencies: - '@vue/compiler-sfc': 3.x - prettier: 2.x - 3.x - peerDependenciesMeta: - '@vue/compiler-sfc': - optional: true + '@tootallnate/once@1.1.2': + optional: true + + '@trivago/prettier-plugin-sort-imports@4.3.0(prettier@2.8.8)': dependencies: '@babel/generator': 7.17.7 '@babel/parser': 7.24.0 @@ -1254,180 +4200,109 @@ packages: prettier: 2.8.8 transitivePeerDependencies: - supports-color - dev: true - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true + '@tsconfig/node10@1.0.9': {} - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true + '@tsconfig/node12@1.0.11': {} - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true + '@tsconfig/node14@1.0.3': {} - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true + '@tsconfig/node16@1.0.4': {} - /@typechain/ethers-v6@0.4.3(ethers@6.11.1)(typechain@8.3.2)(typescript@5.4.2): - resolution: {integrity: sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==} - peerDependencies: - ethers: 6.x - typechain: ^8.3.1 - typescript: '>=4.7.0' + '@typechain/ethers-v6@0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2)': dependencies: ethers: 6.11.1 lodash: 4.17.21 ts-essentials: 7.0.3(typescript@5.4.2) typechain: 8.3.2(typescript@5.4.2) typescript: 5.4.2 - dev: true - /@typechain/hardhat@8.0.3(@typechain/ethers-v6@0.4.3)(ethers@6.11.1)(hardhat@2.21.0)(typechain@8.3.2): - resolution: {integrity: sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==} - peerDependencies: - '@typechain/ethers-v6': ^0.4.3 - ethers: ^6.1.0 - hardhat: ^2.9.9 - typechain: ^8.3.1 + '@typechain/hardhat@8.0.3(@typechain/ethers-v6@0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2))(ethers@6.11.1)(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2))(typechain@8.3.2(typescript@5.4.2))': dependencies: - '@typechain/ethers-v6': 0.4.3(ethers@6.11.1)(typechain@8.3.2)(typescript@5.4.2) + '@typechain/ethers-v6': 0.4.3(ethers@6.11.1)(typechain@8.3.2(typescript@5.4.2))(typescript@5.4.2) ethers: 6.11.1 fs-extra: 9.1.0 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) typechain: 8.3.2(typescript@5.4.2) - dev: true - /@types/bn.js@4.11.6: - resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + '@types/bn.js@4.11.6': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/bn.js@5.1.5: - resolution: {integrity: sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==} + '@types/bn.js@5.1.5': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/chai-as-promised@7.1.8: - resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + '@types/chai-as-promised@7.1.8': dependencies: '@types/chai': 4.3.12 - dev: true - /@types/chai@4.3.12: - resolution: {integrity: sha512-zNKDHG/1yxm8Il6uCCVsm+dRdEsJlFoDu73X17y09bId6UwoYww+vFBsAcRzl8knM1sab3Dp1VRikFQwDOtDDw==} - dev: true + '@types/chai@4.3.12': {} - /@types/concat-stream@1.6.1: - resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} + '@types/concat-stream@1.6.1': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/form-data@0.0.33: - resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} + '@types/form-data@0.0.33': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/fs-extra@9.0.13: - resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + '@types/fs-extra@9.0.13': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + '@types/glob-to-regexp@0.4.4': {} + + '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true + '@types/json-schema@7.0.15': {} - /@types/lru-cache@5.1.1: - resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - dev: true + '@types/keccak@3.0.5': + dependencies: + '@types/node': 18.19.59 - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true + '@types/lru-cache@5.1.1': {} - /@types/mkdirp@0.5.2: - resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} + '@types/minimatch@5.1.2': {} + + '@types/mkdirp@0.5.2': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/mocha@10.0.6: - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} - dev: true + '@types/mocha@10.0.6': {} - /@types/node@10.17.60: - resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - dev: true + '@types/node@10.17.60': {} - /@types/node@18.15.13: - resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} - dev: true + '@types/node@18.15.13': {} - /@types/node@18.19.23: - resolution: {integrity: sha512-wtE3d0OUfNKtZYAqZb8HAWGxxXsImJcPUAgZNw+dWFxO6s5tIwIjyKnY76tsTatsNCLJPkVYwUpq15D38ng9Aw==} + '@types/node@18.19.59': dependencies: undici-types: 5.26.5 - dev: true - /@types/node@8.10.66: - resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} - dev: true + '@types/node@8.10.66': {} - /@types/pbkdf2@3.1.2: - resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} + '@types/pbkdf2@3.1.2': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/prettier@2.7.3: - resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - dev: true + '@types/prettier@2.7.3': {} - /@types/qs@6.9.12: - resolution: {integrity: sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==} - dev: true + '@types/qs@6.9.12': {} - /@types/resolve@0.0.8: - resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} + '@types/resolve@0.0.8': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/secp256k1@4.0.6: - resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} + '@types/secp256k1@4.0.6': dependencies: - '@types/node': 18.19.23 - dev: true + '@types/node': 18.19.59 - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true + '@types/semver@7.5.8': {} - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.2): - resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.2))(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.2) @@ -1441,72 +4316,43 @@ packages: natural-compare-lite: 1.4.0 semver: 7.6.0 tsutils: 3.21.0(typescript@5.4.2) + optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.2): - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.2) debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 + optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - /@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.4.2): - resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.2) '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.2) debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 tsutils: 3.21.0(typescript@5.4.2) + optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + '@typescript-eslint/types@5.62.0': {} - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.2): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.2)': dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 @@ -1515,16 +4361,12 @@ packages: is-glob: 4.0.3 semver: 7.6.0 tsutils: 3.21.0(typescript@5.4.2) + optionalDependencies: typescript: 5.4.2 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.2): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.15 @@ -1538,341 +4380,210 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: true - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 eslint-visitor-keys: 3.4.3 - dev: true - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true + '@ungap/structured-clone@1.2.0': {} - /abbrev@1.0.9: - resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - dev: true + abbrev@1.0.9: {} - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-jsx@5.3.2(acorn@8.11.3): dependencies: acorn: 8.11.3 - dev: true - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn-walk@8.3.2: {} - /address@1.2.2: - resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} - engines: {node: '>= 10.0.0'} - dev: true + acorn@8.11.3: {} - /adm-zip@0.4.16: - resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} - engines: {node: '>=0.3.0'} - dev: true + adm-zip@0.4.16: {} - /aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} - dev: true + aes-js@3.0.0: {} - /aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - dev: true + aes-js@4.0.0-beta.5: {} - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + agent-base@6.0.2: dependencies: debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} + agentkeepalive@4.5.0: + dependencies: + humanize-ms: 1.2.1 + optional: true + + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - dev: true - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.12.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 - dev: true - /amdefine@1.0.1: - resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} - engines: {node: '>=0.4.2'} - requiresBuild: true - dev: true + amazon-cognito-identity-js@6.3.12(encoding@0.1.13): + dependencies: + '@aws-crypto/sha256-js': 1.2.2 + buffer: 4.9.2 + fast-base64-decode: 1.0.0 + isomorphic-unfetch: 3.1.0(encoding@0.1.13) + js-cookie: 2.2.1 + transitivePeerDependencies: + - encoding + + amdefine@1.0.1: optional: true - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 - dev: true - /ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - dev: true + ansi-colors@4.1.1: {} - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true + ansi-colors@4.1.3: {} - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 - dev: true - /ansi-regex@3.0.1: - resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} - engines: {node: '>=4'} - dev: true + ansi-regex@3.0.1: {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + ansi-regex@5.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: true - /antlr4@4.13.1: - resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} - engines: {node: '>=16'} - dev: true + antlr4@4.13.1: {} - /antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - dev: true + antlr4ts@0.5.0-alpha.4: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true + aproba@2.0.0: + optional: true - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + are-we-there-yet@3.0.1: dependencies: - sprintf-js: 1.0.3 - dev: true + delegates: 1.0.0 + readable-stream: 3.6.2 + optional: true - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true + arg@4.1.3: {} - /array-back@3.1.0: - resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} - engines: {node: '>=6'} - dev: true + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 - /array-back@4.0.2: - resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} - engines: {node: '>=8'} - dev: true + argparse@2.0.1: {} - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true + array-back@3.1.0: {} - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true + array-back@4.0.2: {} - /array-uniq@1.0.3: - resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} - engines: {node: '>=0.10.0'} - dev: true + array-union@2.1.0: {} - /array.prototype.findlast@1.2.4: - resolution: {integrity: sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true + array-uniq@1.0.3: {} - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true + asap@2.0.6: {} - /asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: true + assertion-error@1.1.0: {} - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true + ast-parents@0.0.1: {} - /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true + astral-regex@2.0.0: {} - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true + async-retry@1.3.3: + dependencies: + retry: 0.13.1 - /async@1.5.2: - resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} - dev: true + async@1.5.2: {} - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true + asynckit@0.4.0: {} - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - dev: true + at-least-node@1.0.0: {} - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - dev: true - /axios@0.21.4(debug@4.3.4): - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + axios@0.21.4(debug@4.3.4): dependencies: follow-redirects: 1.15.5(debug@4.3.4) transitivePeerDependencies: - debug - dev: true - /axios@1.6.7: - resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} + axios@1.6.7: dependencies: follow-redirects: 1.15.5(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - dev: true - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true + axios@1.7.7(debug@4.3.4): + dependencies: + follow-redirects: 1.15.9(debug@4.3.4) + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug - /base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + balanced-match@1.0.2: {} + + base-x@3.0.9: dependencies: safe-buffer: 5.2.1 - dev: true - /bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} - dev: true + base64-js@1.5.1: {} - /bigint-buffer@1.1.5: - resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} - engines: {node: '>= 10.0.0'} - requiresBuild: true + bech32@1.1.4: {} + + bigint-buffer@1.1.5: dependencies: bindings: 1.5.0 - dev: true - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true + binary-extensions@2.2.0: {} - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 - dev: true - /blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - dev: true + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 - /bn.js@4.11.6: - resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - dev: true + blakejs@1.2.1: {} - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: true + bn.js@4.11.6: {} - /bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: true + bn.js@4.12.0: {} - /boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} + bn.js@5.2.1: {} + + boxen@5.1.2: dependencies: ansi-align: 3.0.1 camelcase: 6.3.0 @@ -1882,38 +4593,25 @@ packages: type-fest: 0.20.2 widest-line: 3.1.0 wrap-ansi: 7.0.0 - dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: true + brorand@1.1.0: {} - /browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - dev: true + browser-stdout@1.3.1: {} - /browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 cipher-base: 1.0.4 @@ -1921,79 +4619,91 @@ packages: evp_bytestokey: 1.0.3 inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - /bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + bs58@4.0.1: dependencies: base-x: 3.0.9 - dev: true - /bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + bs58check@2.1.2: dependencies: bs58: 4.0.1 create-hash: 1.2.0 safe-buffer: 5.2.1 - dev: true - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true + buffer-from@1.1.2: {} - /buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - dev: true + buffer-xor@1.0.3: {} - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bytes@3.1.2: {} + + cacache@15.3.0: + dependencies: + '@npmcli/fs': 1.1.1 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.3 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.2.1 + unique-filename: 1.1.1 + transitivePeerDependencies: + - bluebird + optional: true + + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.2 - dev: true - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true + callsites@3.1.0: {} - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true + camelcase@6.3.0: {} - /caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - dev: true + caseless@0.12.0: {} - /cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} + cbor@8.1.0: dependencies: nofilter: 3.1.0 - dev: true - /chai-as-promised@7.1.1(chai@4.4.1): - resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} - peerDependencies: - chai: '>= 2.1.2 < 5' + cbor@9.0.2: + dependencies: + nofilter: 3.1.0 + + chai-as-promised@7.1.1(chai@4.4.1): dependencies: chai: 4.4.1 check-error: 1.0.3 - dev: true - /chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} + chai@4.4.1: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -2002,38 +4712,25 @@ packages: loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 - dev: true - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - /charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - dev: true + charenc@0.0.2: {} - /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + check-error@1.0.3: dependencies: get-func-name: 2.0.2 - dev: true - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} + chokidar@3.5.3: dependencies: anymatch: 3.1.3 braces: 3.0.2 @@ -2044,11 +4741,8 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: true - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 braces: 3.0.2 @@ -2059,169 +4753,118 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: true - /ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - dev: true + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 - /cipher-base@1.0.4: - resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + chownr@1.1.4: {} + + chownr@2.0.0: {} + + ci-info@2.0.0: {} + + cipher-base@1.0.4: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true + clean-stack@2.2.0: {} - /cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - dev: true + cli-boxes@2.2.1: {} - /cli-table3@0.5.1: - resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} - engines: {node: '>=6'} + cli-table3@0.5.1: dependencies: object-assign: 4.1.1 string-width: 2.1.1 optionalDependencies: colors: 1.4.0 - dev: true - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /colors@1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - dev: true + color-support@1.1.3: + optional: true - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + colors@1.4.0: {} + + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 - dev: true - /command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - dev: true + command-exists@1.2.9: {} - /command-line-args@5.2.1: - resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} - engines: {node: '>=4.0.0'} + command-line-args@5.2.1: dependencies: array-back: 3.1.0 find-replace: 3.0.0 lodash.camelcase: 4.3.0 typical: 4.0.0 - dev: true - /command-line-usage@6.1.3: - resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} - engines: {node: '>=8.0.0'} + command-line-usage@6.1.3: dependencies: array-back: 4.0.2 chalk: 2.4.2 table-layout: 1.0.2 typical: 5.2.0 - dev: true - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true + commander@10.0.1: {} - /commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - dev: true + commander@11.1.0: {} - /commander@3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - dev: true + commander@8.3.0: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + compare-versions@6.1.1: {} - /concat-stream@1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} + concat-map@0.0.1: {} + + concat-stream@1.6.2: dependencies: buffer-from: 1.1.2 inherits: 2.0.4 readable-stream: 2.3.8 typedarray: 0.0.6 - dev: true - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - dev: true + console-control-strings@1.1.0: + optional: true - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true + cookie@0.4.2: {} - /cosmiconfig@8.3.6(typescript@5.4.2): - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true + core-util-is@1.0.3: {} + + cosmiconfig@8.3.6(typescript@5.4.2): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 + optionalDependencies: typescript: 5.4.2 - dev: true - /create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + create-hash@1.2.0: dependencies: cipher-base: 1.0.4 inherits: 2.0.4 md5.js: 1.3.5 ripemd160: 2.0.2 sha.js: 2.4.11 - dev: true - /create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + create-hmac@1.1.7: dependencies: cipher-base: 1.0.4 create-hash: 1.2.0 @@ -2229,150 +4872,79 @@ packages: ripemd160: 2.0.2 safe-buffer: 5.2.1 sha.js: 2.4.11 - dev: true - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true + create-require@1.1.1: {} - /cross-env@7.0.3: - resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} - engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} - hasBin: true + cross-env@7.0.3: dependencies: cross-spawn: 7.0.3 - dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - - /crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - dev: true - /crypto-js@4.2.0: - resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - dev: true + crypt@0.0.2: {} - /death@1.1.0: - resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} - dev: true + death@1.1.0: {} - /debug@4.3.4(supports-color@8.1.1): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4(supports-color@8.1.1): dependencies: ms: 2.1.2 + optionalDependencies: supports-color: 8.1.1 - dev: true - /decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - dev: true + decamelize@4.0.0: {} - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-eql@4.1.3: dependencies: type-detect: 4.0.8 - dev: true - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true + deep-extend@0.6.0: {} - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true + deep-is@0.1.4: {} - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: true - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true + delayed-stream@1.0.0: {} - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true + delegates@1.0.0: + optional: true - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true + depd@2.0.0: {} - /detect-port@1.5.1: - resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} - hasBin: true - dependencies: - address: 1.2.2 - debug: 4.3.4(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - dev: true + dequal@2.0.3: {} - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true + detect-libc@2.0.3: {} - /diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - dev: true + diff@4.0.2: {} - /difflib@0.2.4: - resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + diff@5.0.0: {} + + difflib@0.2.4: dependencies: heap: 0.2.7 - dev: true - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dev: true - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} + doctrine@3.0.0: dependencies: esutils: 2.0.3 - dev: true - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: true + dotenv@16.4.5: {} - /elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + elliptic@6.5.4: dependencies: bn.js: 4.12.0 brorand: 1.1.0 @@ -2381,10 +4953,8 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true - /elliptic@6.5.5: - resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==} + elliptic@6.5.5: dependencies: bn.js: 4.12.0 brorand: 1.1.0 @@ -2393,137 +4963,47 @@ packages: inherits: 2.0.4 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /encode-utf8@1.0.3: - resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} - dev: true + encode-utf8@1.0.3: {} - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} + encoding@0.1.13: dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - dev: true - - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true + iconv-lite: 0.6.3 + optional: true - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + end-of-stream@1.4.4: dependencies: - is-arrayish: 0.2.1 - dev: true + once: 1.4.0 - /es-abstract@1.22.5: - resolution: {integrity: sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==} - engines: {node: '>= 0.4'} + enquirer@2.4.1: dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.5 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true + env-paths@2.2.1: {} - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true + err-code@2.0.3: + optional: true - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} + error-ex@1.3.2: dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true + is-arrayish: 0.2.1 - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + es-define-property@1.0.0: dependencies: - hasown: 2.0.2 - dev: true + get-intrinsic: 1.2.4 - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true + es-errors@1.3.0: {} - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true + escalade@3.1.2: {} - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true + escape-string-regexp@1.0.5: {} - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true + escape-string-regexp@4.0.0: {} - /escodegen@1.8.1: - resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} - engines: {node: '>=0.12.0'} - hasBin: true + escodegen@1.8.1: dependencies: esprima: 2.7.3 estraverse: 1.9.3 @@ -2531,42 +5011,24 @@ packages: optionator: 0.8.3 optionalDependencies: source-map: 0.2.0 - dev: true - /eslint-config-prettier@8.10.0(eslint@8.57.0): - resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' + eslint-config-prettier@8.10.0(eslint@8.57.0): dependencies: eslint: 8.57.0 - dev: true - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 estraverse: 4.3.0 - dev: true - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - dev: true - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + eslint-visitor-keys@3.4.3: {} - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/regexpp': 4.10.0 @@ -2608,70 +5070,34 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color - dev: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + espree@9.6.1: dependencies: acorn: 8.11.3 acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 - dev: true - /esprima@2.7.3: - resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} - engines: {node: '>=0.10.0'} - hasBin: true - dev: true + esprima@2.7.3: {} - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true + esprima@4.0.1: {} - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} + esquery@1.5.0: dependencies: estraverse: 5.3.0 - dev: true - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 - dev: true - /estraverse@1.9.3: - resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} - engines: {node: '>=0.10.0'} - dev: true + estraverse@1.9.3: {} - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true + estraverse@4.3.0: {} - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true + estraverse@5.3.0: {} - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true + esutils@2.0.3: {} - /eth-gas-reporter@0.2.27: - resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==} - peerDependencies: - '@codechecks/client': ^0.1.0 - peerDependenciesMeta: - '@codechecks/client': - optional: true + eth-gas-reporter@0.2.27: dependencies: '@solidity-parser/parser': 0.14.5 axios: 1.6.7 @@ -2690,16 +5116,12 @@ packages: - bufferutil - debug - utf-8-validate - dev: true - /ethereum-bloom-filters@1.0.10: - resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} + ethereum-bloom-filters@1.0.10: dependencies: js-sha3: 0.8.0 - dev: true - /ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + ethereum-cryptography@0.1.3: dependencies: '@types/pbkdf2': 3.1.2 '@types/secp256k1': 4.0.6 @@ -2716,35 +5138,27 @@ packages: scrypt-js: 3.0.1 secp256k1: 4.0.3 setimmediate: 1.0.5 - dev: true - /ethereum-cryptography@1.2.0: - resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} + ethereum-cryptography@1.2.0: dependencies: '@noble/hashes': 1.2.0 '@noble/secp256k1': 1.7.1 '@scure/bip32': 1.1.5 '@scure/bip39': 1.1.1 - dev: true - /ethereum-cryptography@2.1.3: - resolution: {integrity: sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==} + ethereum-cryptography@2.1.3: dependencies: '@noble/curves': 1.3.0 '@noble/hashes': 1.3.3 '@scure/bip32': 1.3.3 '@scure/bip39': 1.2.2 - dev: true - /ethereumjs-abi@0.6.8: - resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + ethereumjs-abi@0.6.8: dependencies: bn.js: 4.12.0 ethereumjs-util: 6.2.1 - dev: true - /ethereumjs-util@6.2.1: - resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + ethereumjs-util@6.2.1: dependencies: '@types/bn.js': 4.11.6 bn.js: 4.12.0 @@ -2753,21 +5167,16 @@ packages: ethereum-cryptography: 0.1.3 ethjs-util: 0.1.6 rlp: 2.2.7 - dev: true - /ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} + ethereumjs-util@7.1.5: dependencies: '@types/bn.js': 5.1.5 bn.js: 5.2.1 create-hash: 1.2.0 ethereum-cryptography: 0.1.3 rlp: 2.2.7 - dev: true - /ethers@5.7.2: - resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} + ethers@5.7.2: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -2802,11 +5211,8 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true - /ethers@6.11.1: - resolution: {integrity: sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==} - engines: {node: '>=14.0.0'} + ethers@6.11.1: dependencies: '@adraffy/ens-normalize': 1.10.1 '@noble/curves': 1.2.0 @@ -2818,343 +5224,238 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true - /ethjs-unit@0.1.6: - resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} - engines: {node: '>=6.5.0', npm: '>=3'} + ethjs-unit@0.1.6: dependencies: bn.js: 4.11.6 number-to-bn: 1.7.0 - dev: true - /ethjs-util@0.1.6: - resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} - engines: {node: '>=6.5.0', npm: '>=3'} + ethjs-util@0.1.6: dependencies: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 - dev: true - /evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 safe-buffer: 5.2.1 - dev: true - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true + expand-template@2.0.3: {} - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true + extra-bigint@1.2.0: {} - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} + fast-base64-decode@1.0.0: {} + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true + fast-json-stable-stringify@2.1.0: {} - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true + fast-levenshtein@2.0.6: {} - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fastq@1.17.1: dependencies: reusify: 1.0.4 - dev: true - /fhevm@0.4.0(hardhat@2.21.0): - resolution: {integrity: sha512-UuOYMgAodOoGX69G6EXzb7QRes80KeUzDOhRNEqXh7l4npC/0JZXVNoqKwSRe0hGQJE6Qwx+FforPhs5rPzXtg==} + fetch-mock@11.1.5: + dependencies: + '@types/glob-to-regexp': 0.4.4 + dequal: 2.0.3 + glob-to-regexp: 0.4.1 + is-subset: 0.1.1 + regexparam: 3.0.0 + + fhevm-core-contracts@0.1.0-2: {} + + fhevm@0.6.0-0: dependencies: '@openzeppelin/contracts': 5.0.2 - hardhat-preprocessor: 0.1.5(hardhat@2.21.0) + extra-bigint: 1.2.0 + sqlite3: 5.1.7 transitivePeerDependencies: - - hardhat - dev: true + - bluebird + - supports-color - /fhevmjs@0.4.0-7: - resolution: {integrity: sha512-3SiLl9J8HmvVwP4hfAsvpbWb9DlgxOB+zQJzKV8adO8sLcxlO0pWINKqsdL6wnuPqYt2v4WQa+bViLC2NeSi9A==} - hasBin: true + fhevmjs@0.6.0-4: dependencies: + '@types/keccak': 3.0.5 bigint-buffer: 1.1.5 commander: 11.1.0 - crypto-js: 4.2.0 - ethers: 6.11.1 - libsodium: 0.7.13 - libsodium-wrappers: 0.7.13 - node-tfhe: 0.5.3 - tfhe: 0.5.3 + fetch-mock: 11.1.5 + node-tfhe: 0.8.6 + node-tkms: 0.9.0-rc3 + sha3: 2.1.4 + tfhe: 0.8.6 + tkms: 0.9.0-rc3 + url: 0.11.4 + web3-validator: 2.0.6 transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true + - node-fetch - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 - dev: true - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: true + file-uri-to-path@1.0.0: {} - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /find-replace@3.0.0: - resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} - engines: {node: '>=4.0.0'} + find-replace@3.0.0: dependencies: array-back: 3.1.0 - dev: true - /find-up@2.1.0: - resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} - engines: {node: '>=4'} + find-up@2.1.0: dependencies: locate-path: 2.0.0 - dev: true - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true - - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + + flat-cache@3.2.0: dependencies: flatted: 3.3.1 keyv: 4.5.4 rimraf: 3.0.2 - dev: true - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true + flat@5.0.2: {} - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true + flatted@3.3.1: {} - /fmix@0.1.0: - resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} + fmix@0.1.0: dependencies: imul: 1.0.1 - dev: true - /follow-redirects@1.15.5(debug@4.3.4): - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: + follow-redirects@1.15.5(debug@4.3.4): + optionalDependencies: debug: 4.3.4(supports-color@8.1.1) - dev: true - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + follow-redirects@1.15.9(debug@4.3.4): + optionalDependencies: + debug: 4.3.4(supports-color@8.1.1) + + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: true - /form-data@2.5.1: - resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} - engines: {node: '>= 0.12'} + form-data@2.5.1: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true - /form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} + form-data@4.0.0: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true - /fp-ts@1.19.3: - resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - dev: true + fp-ts@1.19.3: {} - /fs-extra@0.30.0: - resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 2.4.0 - klaw: 1.3.1 - path-is-absolute: 1.0.1 - rimraf: 2.7.1 - dev: true + fs-constants@1.0.0: {} - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: true - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} + fs-extra@9.1.0: dependencies: at-least-node: 1.0.0 graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: true - /fs-readdir-recursive@1.1.0: - resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} - dev: true + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true + fs-readdir-recursive@1.1.0: {} - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fs.realpath@1.0.0: {} + + fsevents@2.3.3: optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true + function-bind@1.1.2: {} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} + gauge@4.0.4: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + optional: true - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - dev: true + get-func-name@2.0.2: {} - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.2 - dev: true - - /get-port@3.2.0: - resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} - engines: {node: '>=4'} - dev: true - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true + get-port@3.2.0: {} - /ghost-testrpc@0.0.2: - resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} - hasBin: true + ghost-testrpc@0.0.2: dependencies: chalk: 2.4.2 node-emoji: 1.11.0 - dev: true - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + github-from-package@0.0.0: {} + + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@5.0.15: - resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} + glob-to-regexp@0.4.1: {} + + glob@5.0.15: dependencies: inflight: 1.0.6 inherits: 2.0.4 minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + glob@7.1.7: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3162,10 +5463,8 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + glob@7.2.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3173,10 +5472,8 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + glob@7.2.3: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3184,67 +5481,39 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} + glob@8.1.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 minimatch: 5.0.1 once: 1.4.0 - dev: true - /glob@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} + glob@9.3.5: dependencies: fs.realpath: 1.0.0 minimatch: 8.0.4 minipass: 4.2.8 path-scurry: 1.10.1 - dev: true - /global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} + global-modules@2.0.0: dependencies: global-prefix: 3.0.0 - dev: true - /global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} + global-prefix@3.0.0: dependencies: ini: 1.3.8 kind-of: 6.0.3 which: 1.3.1 - dev: true - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true + globals@11.12.0: {} - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} + globals@13.24.0: dependencies: type-fest: 0.20.2 - dev: true - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - dev: true - /globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} + globby@10.0.2: dependencies: '@types/glob': 7.2.0 array-union: 2.1.0 @@ -3254,11 +5523,8 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -3266,26 +5532,16 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 - dev: true - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true + graceful-fs@4.2.11: {} - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true + graphemer@1.4.0: {} - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true + handlebars@4.7.8: dependencies: minimist: 1.2.8 neo-async: 2.6.2 @@ -3293,10 +5549,8 @@ packages: wordwrap: 1.0.0 optionalDependencies: uglify-js: 3.17.4 - dev: true - /hardhat-deploy@0.11.45: - resolution: {integrity: sha512-aC8UNaq3JcORnEUIwV945iJuvBwi65tjHVDU3v6mOcqik7WAzHVCJ7cwmkkipsHrWysrB5YvGF1q9S1vIph83w==} + hardhat-deploy@0.11.45: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -3326,48 +5580,35 @@ packages: - bufferutil - supports-color - utf-8-validate - dev: true - /hardhat-gas-reporter@1.0.10(hardhat@2.21.0): - resolution: {integrity: sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==} - peerDependencies: - hardhat: ^2.0.2 + hardhat-gas-reporter@1.0.10(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)): dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' - bufferutil - debug - utf-8-validate - dev: true - /hardhat-preprocessor@0.1.5(hardhat@2.21.0): - resolution: {integrity: sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g==} - peerDependencies: - hardhat: ^2.0.5 + hardhat-ignore-warnings@0.2.11: + dependencies: + minimatch: 5.1.6 + node-interval-tree: 2.1.2 + solidity-comments: 0.0.2 + + hardhat-preprocessor@0.1.5(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)): dependencies: - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) murmur-128: 0.2.1 - dev: true - /hardhat@2.21.0(ts-node@10.9.2)(typescript@5.4.2): - resolution: {integrity: sha512-8DlJAVJDEVHaV1sh9FLuKLLgCFv9EAJ+M+8IbjSIPgoeNo3ss5L1HgGBMfnI88c7OzMEZkdcuyGoobFeK3Orqw==} - hasBin: true - peerDependencies: - ts-node: '*' - typescript: '*' - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true + hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 - '@nomicfoundation/edr': 0.2.1 + '@nomicfoundation/edr': 0.6.4 '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 @@ -3380,7 +5621,7 @@ packages: ansi-escapes: 4.3.2 boxen: 5.1.2 chalk: 2.4.2 - chokidar: 3.6.0 + chokidar: 4.0.1 ci-info: 2.0.0 debug: 4.3.4(supports-color@8.1.1) enquirer: 2.4.1 @@ -3393,6 +5634,7 @@ packages: glob: 7.2.0 immutable: 4.3.5 io-ts: 1.10.4 + json-stream-stringify: 3.1.6 keccak: 3.0.4 lodash: 4.17.21 mnemonist: 0.38.5 @@ -3401,701 +5643,467 @@ packages: raw-body: 2.5.2 resolve: 1.17.0 semver: 6.3.1 - solc: 0.7.3(debug@4.3.4) + solc: 0.8.26(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.2(@types/node@18.19.23)(typescript@5.4.2) tsort: 0.0.1 - typescript: 5.4.2 undici: 5.28.3 uuid: 8.3.2 ws: 7.5.9 + optionalDependencies: + ts-node: 10.9.2(@types/node@18.19.59)(typescript@5.4.2) + typescript: 5.4.2 transitivePeerDependencies: - bufferutil - c-kzg - supports-color - utf-8-validate - dev: true - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true + has-flag@1.0.0: {} - /has-flag@1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 - dev: true - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true + has-proto@1.0.3: {} - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true + has-symbols@1.0.3: {} - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - dev: true - /hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} + has-unicode@2.0.1: + optional: true + + hash-base@3.1.0: dependencies: inherits: 2.0.4 readable-stream: 3.6.2 safe-buffer: 5.2.1 - dev: true - /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hash.js@1.1.7: dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 - dev: true - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + hasown@2.0.2: dependencies: function-bind: 1.1.2 - dev: true - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true + he@1.2.0: {} - /heap@0.2.7: - resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} - dev: true + heap@0.2.7: {} - /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + hmac-drbg@1.0.1: dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - dev: true - /http-basic@8.1.3: - resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} - engines: {node: '>=6.0.0'} + http-basic@8.1.3: dependencies: caseless: 0.12.0 concat-stream: 1.6.2 http-response-object: 3.0.2 parse-cache-control: 1.0.1 - dev: true - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} + http-cache-semantics@4.1.1: + optional: true + + http-errors@2.0.0: dependencies: depd: 2.0.0 inherits: 2.0.4 setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: true - /http-response-object@3.0.2: - resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} + http-proxy-agent@4.0.1: + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + optional: true + + http-response-object@3.0.2: dependencies: '@types/node': 10.17.60 - dev: true - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + optional: true + + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - dev: true - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true - /immutable@4.3.5: - resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==} - dev: true + ieee754@1.2.1: {} - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} + ignore@5.3.1: {} + + immutable@4.3.5: {} + + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true - /imul@1.0.1: - resolution: {integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==} - engines: {node: '>=0.10.0'} - dev: true + imul@1.0.1: {} - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true + imurmurhash@0.1.4: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + indent-string@4.0.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + infer-owner@1.0.4: + optional: true + + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true + inherits@2.0.4: {} - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true + ini@1.3.8: {} - /interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: true + interpret@1.4.0: {} - /io-ts@1.10.4: - resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + io-ts@1.10.4: dependencies: fp-ts: 1.19.3 - dev: true - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + ip-address@9.0.5: dependencies: - binary-extensions: 2.2.0 - dev: true + jsbn: 1.1.0 + sprintf-js: 1.1.3 + optional: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - /is-hex-prefixed@1.0.0: - resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} - engines: {node: '>=6.5.0', npm: '>=3'} - dev: true - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true + is-arrayish@0.2.1: {} - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-binary-path@2.1.0: dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - dev: true + binary-extensions: 2.2.0 - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true + is-callable@1.2.7: {} - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} + is-core-module@2.13.1: dependencies: - call-bind: 1.0.7 - dev: true + hasown: 2.0.2 - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-extglob@2.1.1: {} + + is-fullwidth-code-point@2.0.0: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 - dev: true - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + is-glob@4.0.3: dependencies: - has-symbols: 1.0.3 - dev: true + is-extglob: 2.1.1 - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} + is-hex-prefixed@1.0.0: {} + + is-lambda@1.0.1: + optional: true + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + is-plain-obj@2.1.0: {} + + is-subset@0.1.1: {} + + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 - dev: true - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true + is-unicode-supported@0.1.0: {} - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true + isarray@1.0.0: {} - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true + isexe@2.0.0: {} - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true + isomorphic-unfetch@3.1.0(encoding@0.1.13): + dependencies: + node-fetch: 2.7.0(encoding@0.1.13) + unfetch: 4.2.0 + transitivePeerDependencies: + - encoding - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + javascript-natural-sort@0.7.1: {} - /javascript-natural-sort@0.7.1: - resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} - dev: true + js-cookie@2.2.1: {} - /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: true + js-sha3@0.8.0: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + js-tokens@4.0.0: {} - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - dev: true - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - dev: true - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true + jsbn@1.1.0: + optional: true - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true + jsesc@2.5.2: {} - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + json-buffer@3.0.1: {} - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true + json-parse-even-better-errors@2.3.1: {} - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true + json-schema-traverse@0.4.1: {} - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true + json-schema-traverse@1.0.0: {} - /jsonfile@2.4.0: - resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true + json-stable-stringify-without-jsonify@1.0.1: {} - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + json-stream-stringify@3.1.6: {} + + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 - dev: true - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonfile@6.1.0: dependencies: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: true - /jsonschema@1.4.1: - resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} - dev: true + jsonschema@1.4.1: {} - /keccak@3.0.4: - resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} - engines: {node: '>=10.0.0'} - requiresBuild: true + keccak@3.0.4: dependencies: node-addon-api: 2.0.2 node-gyp-build: 4.8.0 readable-stream: 3.6.2 - dev: true - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 - dev: true - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /klaw@1.3.1: - resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true + kind-of@6.0.3: {} - /levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} + levn@0.3.0: dependencies: prelude-ls: 1.1.2 type-check: 0.3.2 - dev: true - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - - /libsodium-wrappers@0.7.13: - resolution: {integrity: sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==} - dependencies: - libsodium: 0.7.13 - dev: true - - /libsodium@0.7.13: - resolution: {integrity: sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw==} - dev: true - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + lines-and-columns@1.2.4: {} - /locate-path@2.0.0: - resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} - engines: {node: '>=4'} + locate-path@2.0.0: dependencies: p-locate: 2.0.0 path-exists: 3.0.0 - dev: true - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - dev: true - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: true + lodash.camelcase@4.3.0: {} - /lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - dev: true + lodash.clonedeep@4.5.0: {} - /lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - dev: true + lodash.isequal@4.5.0: {} - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true + lodash.merge@4.6.2: {} - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true + lodash.truncate@4.4.2: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true + lodash@4.17.21: {} - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 - dev: true - /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + loupe@2.3.7: dependencies: get-func-name: 2.0.2 - dev: true - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true + lru-cache@10.2.0: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - dev: true - /lru_map@0.3.3: - resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - dev: true + lru_map@0.3.3: {} - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true + make-error@1.3.6: {} - /markdown-table@1.1.3: - resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} - dev: true + make-fetch-happen@9.1.0: + dependencies: + agentkeepalive: 4.5.0 + cacache: 15.3.0 + http-cache-semantics: 4.1.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 1.4.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 6.2.1 + ssri: 8.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + optional: true - /match-all@1.2.6: - resolution: {integrity: sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==} - dev: true + markdown-table@1.1.3: {} - /md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + match-all@1.2.6: {} + + md5.js@1.3.5: dependencies: hash-base: 3.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true + memorystream@0.3.1: {} - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true + merge2@1.4.1: {} - /micro-ftch@0.3.1: - resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} - dev: true + micro-ftch@0.3.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromatch@4.0.5: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true + mime-db@1.52.0: {} - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - dev: true - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true + mimic-response@3.1.0: {} - /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: true + minimalistic-assert@1.0.1: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimalistic-crypto-utils@1.0.1: {} + + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - dev: true - /minimatch@5.0.1: - resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} - engines: {node: '>=10'} + minimatch@5.0.1: dependencies: brace-expansion: 2.0.1 - dev: true - /minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 - dev: true - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true + minimatch@8.0.4: + dependencies: + brace-expansion: 2.0.1 - /minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - dev: true + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true + minimist@1.2.8: {} - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + optional: true + + minipass-fetch@1.4.1: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + optional: true + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + optional: true + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + optional: true + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + optional: true + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@4.2.8: {} + + minipass@5.0.0: {} + + minipass@7.0.4: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp-classic@0.5.3: {} + + mkdirp@0.5.6: dependencies: minimist: 1.2.8 - dev: true - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true + mkdirp@1.0.4: {} - /mnemonist@0.38.5: - resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + mnemonist@0.38.5: dependencies: obliterator: 2.0.4 - dev: true - /mocha@10.3.0: - resolution: {integrity: sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==} - engines: {node: '>= 14.0.0'} - hasBin: true + mocha@10.3.0: dependencies: ansi-colors: 4.1.1 browser-stdout: 1.3.1 @@ -4117,117 +6125,110 @@ packages: yargs: 16.2.0 yargs-parser: 20.2.4 yargs-unparser: 2.0.0 - dev: true - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + ms@2.1.2: {} - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true + ms@2.1.3: {} - /murmur-128@0.2.1: - resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} + murmur-128@0.2.1: dependencies: encode-utf8: 1.0.3 fmix: 0.1.0 imul: 1.0.1 - dev: true - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true + napi-build-utils@1.0.2: {} - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true + natural-compare-lite@1.4.0: {} - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true + natural-compare@1.4.0: {} - /node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - dev: true + negotiator@0.6.4: + optional: true - /node-emoji@1.11.0: - resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} + neo-async@2.6.2: {} + + node-abi@3.71.0: + dependencies: + semver: 7.6.0 + + node-addon-api@2.0.2: {} + + node-addon-api@7.1.1: {} + + node-emoji@1.11.0: dependencies: lodash: 4.17.21 - dev: true - /node-gyp-build@4.8.0: - resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} - hasBin: true - dev: true + node-fetch@2.7.0(encoding@0.1.13): + dependencies: + whatwg-url: 5.0.0 + optionalDependencies: + encoding: 0.1.13 - /node-tfhe@0.5.3: - resolution: {integrity: sha512-72HFj9Lj9hC5PWaW5TH306uPAUUL6We2lAXLW6ibxwsLcSUgEL7NEVGz5MqAYa5PcwpVEvzLDZSHCFRz8glqaQ==} - dev: true + node-gyp-build@4.8.0: {} - /nofilter@3.1.0: - resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} - engines: {node: '>=12.19'} - dev: true + node-gyp@8.4.1: + dependencies: + env-paths: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + make-fetch-happen: 9.1.0 + nopt: 5.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.6.0 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + optional: true - /nopt@3.0.6: - resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} - hasBin: true + node-interval-tree@2.1.2: dependencies: - abbrev: 1.0.9 - dev: true + shallowequal: 1.1.0 - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + node-tfhe@0.8.6: {} - /number-to-bn@1.7.0: - resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} - engines: {node: '>=6.5.0', npm: '>=3'} + node-tkms@0.9.0-rc3: {} + + nofilter@3.1.0: {} + + nopt@3.0.6: dependencies: - bn.js: 4.11.6 - strip-hex-prefix: 1.0.0 - dev: true + abbrev: 1.0.9 - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true + nopt@5.0.0: + dependencies: + abbrev: 1.0.9 + optional: true - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true + normalize-path@3.0.0: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true + npmlog@6.0.2: + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + optional: true - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} + number-to-bn@1.7.0: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true + bn.js: 4.11.6 + strip-hex-prefix: 1.0.0 - /obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - dev: true + object-assign@4.1.1: {} - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + object-inspect@1.13.1: {} + + obliterator@2.0.4: {} + + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: true - /optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} + optionator@0.8.3: dependencies: deep-is: 0.1.4 fast-levenshtein: 2.0.6 @@ -4235,11 +6236,8 @@ packages: prelude-ls: 1.1.2 type-check: 0.3.2 word-wrap: 1.2.5 - dev: true - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} + optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 @@ -4247,233 +6245,174 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - /ordinal@1.0.3: - resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} - dev: true + ordinal@1.0.3: {} - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true + os-tmpdir@1.0.2: {} - /p-limit@1.3.0: - resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} - engines: {node: '>=4'} + p-limit@1.3.0: dependencies: p-try: 1.0.0 - dev: true - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - dev: true - /p-locate@2.0.0: - resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} - engines: {node: '>=4'} + p-locate@2.0.0: dependencies: p-limit: 1.3.0 - dev: true - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - dev: true - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} + p-map@4.0.0: dependencies: aggregate-error: 3.1.0 - dev: true - /p-try@1.0.0: - resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} - engines: {node: '>=4'} - dev: true + p-try@1.0.0: {} - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + parent-module@1.0.1: dependencies: callsites: 3.1.0 - dev: true - /parse-cache-control@1.0.1: - resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} - dev: true + parse-cache-control@1.0.1: {} - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true - /path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true + path-exists@3.0.0: {} - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true + path-is-absolute@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true + path-parse@1.0.7: {} - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.10.1: dependencies: lru-cache: 10.2.0 minipass: 7.0.4 - dev: true - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true + path-type@4.0.0: {} - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true + pathval@1.1.1: {} - /pbkdf2@3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} + pbkdf2@3.1.2: dependencies: create-hash: 1.2.0 create-hmac: 1.1.7 ripemd160: 2.0.2 safe-buffer: 5.2.1 sha.js: 2.4.11 - dev: true - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true + pify@4.0.1: {} - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true + pluralize@8.0.0: {} - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true + possible-typed-array-names@1.0.0: {} - /prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true + prebuild-install@7.1.2: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.71.0 + pump: 3.0.2 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true + prelude-ls@1.1.2: {} - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.3.0 - dev: true - /prettier-plugin-solidity@1.3.1(prettier@2.8.8): - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' + prettier-plugin-solidity@1.3.1(prettier@2.8.8): dependencies: '@solidity-parser/parser': 0.17.0 prettier: 2.8.8 semver: 7.6.0 solidity-comments-extractor: 0.0.8 - dev: true - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true + prettier@2.8.8: {} - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true + process-nextick-args@2.0.1: {} - /promise@8.3.0: - resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + promise-inflight@1.0.1: + optional: true + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + optional: true + + promise@8.3.0: dependencies: asap: 2.0.6 - dev: true - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true + proxy-from-env@1.1.0: {} - /qs@6.12.0: - resolution: {integrity: sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==} - engines: {node: '>=0.6'} + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + qs@6.12.0: dependencies: side-channel: 1.0.6 - dev: true - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true + qs@6.13.0: + dependencies: + side-channel: 1.0.6 - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + queue-microtask@1.2.3: {} + + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 - dev: true - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} + raw-body@2.5.2: dependencies: bytes: 3.1.2 http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: true - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 inherits: 2.0.4 @@ -4482,187 +6421,93 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@3.6.0: dependencies: picomatch: 2.3.1 - dev: true - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} + readdirp@4.0.2: {} + + rechoir@0.6.2: dependencies: resolve: 1.22.8 - dev: true - /recursive-readdir@2.2.3: - resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} - engines: {node: '>=6.0.0'} + recursive-readdir@2.2.3: dependencies: minimatch: 3.1.2 - dev: true - /reduce-flatten@2.0.0: - resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} - engines: {node: '>=6'} - dev: true + reduce-flatten@2.0.0: {} - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true + regexparam@3.0.0: {} - /req-cwd@2.0.0: - resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} - engines: {node: '>=4'} + req-cwd@2.0.0: dependencies: req-from: 2.0.0 - dev: true - /req-from@2.0.0: - resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} - engines: {node: '>=4'} + req-from@2.0.0: dependencies: resolve-from: 3.0.0 - dev: true - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + require-directory@2.1.1: {} - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true + require-from-string@2.0.2: {} - /resolve-from@3.0.0: - resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} - engines: {node: '>=4'} - dev: true + resolve-from@3.0.0: {} - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true + resolve-from@4.0.0: {} - /resolve@1.1.7: - resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} - dev: true + resolve@1.1.7: {} - /resolve@1.17.0: - resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + resolve@1.17.0: dependencies: path-parse: 1.0.7 - dev: true - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true + resolve@1.22.8: dependencies: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true + retry@0.12.0: {} - /rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true + retry@0.13.1: {} - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true + reusify@1.0.4: {} + + rimraf@3.0.2: dependencies: glob: 7.2.3 - dev: true - /rimraf@4.4.1: - resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} - engines: {node: '>=14'} - hasBin: true + rimraf@4.4.1: dependencies: glob: 9.3.5 - dev: true - /ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + ripemd160@2.0.2: dependencies: hash-base: 3.1.0 inherits: 2.0.4 - dev: true - /rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true + rlp@2.2.7: dependencies: bn.js: 5.2.1 - dev: true - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: true - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + safe-buffer@5.1.2: {} - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true + safe-buffer@5.2.1: {} - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true + safer-buffer@2.1.2: {} - /sc-istanbul@0.4.6: - resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} - hasBin: true + sc-istanbul@0.4.6: dependencies: abbrev: 1.0.9 async: 1.5.2 @@ -4678,49 +6523,31 @@ packages: supports-color: 3.2.3 which: 1.3.1 wordwrap: 1.0.0 - dev: true - /scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - dev: true + scrypt-js@3.0.1: {} - /secp256k1@4.0.3: - resolution: {integrity: sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==} - engines: {node: '>=10.0.0'} - requiresBuild: true + secp256k1@4.0.3: dependencies: elliptic: 6.5.5 node-addon-api: 2.0.2 node-gyp-build: 4.8.0 - dev: true - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true + semver@5.7.2: {} - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true + semver@6.3.1: {} - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true + semver@7.6.0: dependencies: lru-cache: 6.0.0 - dev: true - /serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + serialize-javascript@6.0.0: dependencies: randombytes: 2.1.0 - dev: true - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + set-blocking@2.0.0: + optional: true + + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -4728,119 +6555,101 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: true - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true + setimmediate@1.0.5: {} - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true + setprototypeof@1.2.0: {} - /sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true + sha.js@2.4.11: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - /sha1@1.1.1: - resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} + sha1@1.1.1: dependencies: charenc: 0.0.2 crypt: 0.0.2 - dev: true - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + sha3@2.1.4: + dependencies: + buffer: 6.0.3 + + shallowequal@1.1.0: {} + + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true + shebang-regex@3.0.0: {} - /shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true + shelljs@0.8.5: dependencies: glob: 7.2.3 interpret: 1.4.0 rechoir: 0.6.2 - dev: true - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 object-inspect: 1.13.1 - dev: true - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + signal-exit@3.0.7: {} - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + + slash@3.0.0: {} + + slice-ansi@4.0.0: dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - dev: true - /solc@0.7.3(debug@4.3.4): - resolution: {integrity: sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==} - engines: {node: '>=8.0.0'} - hasBin: true + smart-buffer@4.2.0: + optional: true + + socks-proxy-agent@6.2.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.4(supports-color@8.1.1) + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + optional: true + + socks@2.8.3: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + optional: true + + solc@0.8.26(debug@4.3.4): dependencies: command-exists: 1.2.9 - commander: 3.0.2 + commander: 8.3.0 follow-redirects: 1.15.5(debug@4.3.4) - fs-extra: 0.30.0 js-sha3: 0.8.0 memorystream: 0.3.1 - require-from-string: 2.0.2 semver: 5.7.2 tmp: 0.0.33 transitivePeerDependencies: - debug - dev: true - /solhint-plugin-prettier@0.0.5(prettier-plugin-solidity@1.3.1)(prettier@2.8.8): - resolution: {integrity: sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==} - peerDependencies: - prettier: ^1.15.0 || ^2.0.0 - prettier-plugin-solidity: ^1.0.0-alpha.14 + solhint-plugin-prettier@0.0.5(prettier-plugin-solidity@1.3.1(prettier@2.8.8))(prettier@2.8.8): dependencies: prettier: 2.8.8 prettier-linter-helpers: 1.0.0 prettier-plugin-solidity: 1.3.1(prettier@2.8.8) - dev: true - /solhint@3.6.2(typescript@5.4.2): - resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} - hasBin: true + solhint@3.6.2(typescript@5.4.2): dependencies: '@solidity-parser/parser': 0.16.2 ajv: 6.12.6 @@ -4863,35 +6672,66 @@ packages: prettier: 2.8.8 transitivePeerDependencies: - typescript - dev: true - /solidity-ast@0.4.55: - resolution: {integrity: sha512-qeEU/r/K+V5lrAw8iswf2/yfWAnSGs3WKPHI+zAFKFjX0dIBVXEU/swQ8eJQYHf6PJWUZFO2uWV4V1wEOkeQbA==} - dependencies: - array.prototype.findlast: 1.2.4 - dev: true + solidity-ast@0.4.59: {} - /solidity-comments-extractor@0.0.8: - resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - dev: true + solidity-comments-darwin-arm64@0.0.2: + optional: true - /solidity-coverage@0.8.6(hardhat@2.21.0): - resolution: {integrity: sha512-vV03mA/0nNMskOdVwNarUcqk0N/aYdelxAbf6RZ5l84FcYHbqDTr2JXyeYMp4bT48qHtAQjnKrygW1FrECyWNw==} - hasBin: true - peerDependencies: - hardhat: ^2.11.0 + solidity-comments-darwin-x64@0.0.2: + optional: true + + solidity-comments-extractor@0.0.8: {} + + solidity-comments-freebsd-x64@0.0.2: + optional: true + + solidity-comments-linux-arm64-gnu@0.0.2: + optional: true + + solidity-comments-linux-arm64-musl@0.0.2: + optional: true + + solidity-comments-linux-x64-gnu@0.0.2: + optional: true + + solidity-comments-linux-x64-musl@0.0.2: + optional: true + + solidity-comments-win32-arm64-msvc@0.0.2: + optional: true + + solidity-comments-win32-ia32-msvc@0.0.2: + optional: true + + solidity-comments-win32-x64-msvc@0.0.2: + optional: true + + solidity-comments@0.0.2: + optionalDependencies: + solidity-comments-darwin-arm64: 0.0.2 + solidity-comments-darwin-x64: 0.0.2 + solidity-comments-freebsd-x64: 0.0.2 + solidity-comments-linux-arm64-gnu: 0.0.2 + solidity-comments-linux-arm64-musl: 0.0.2 + solidity-comments-linux-x64-gnu: 0.0.2 + solidity-comments-linux-x64-musl: 0.0.2 + solidity-comments-win32-arm64-msvc: 0.0.2 + solidity-comments-win32-ia32-msvc: 0.0.2 + solidity-comments-win32-x64-msvc: 0.0.2 + + solidity-coverage@0.8.12(hardhat@2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2)): dependencies: '@ethersproject/abi': 5.7.0 '@solidity-parser/parser': 0.18.0 chalk: 2.4.2 death: 1.1.0 - detect-port: 1.5.1 difflib: 0.2.4 fs-extra: 8.1.0 ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) + hardhat: 2.22.14(ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2))(typescript@5.4.2) jsonschema: 1.4.1 lodash: 4.17.21 mocha: 10.3.0 @@ -4902,226 +6742,158 @@ packages: semver: 7.6.0 shelljs: 0.8.5 web3-utils: 1.10.4 - transitivePeerDependencies: - - supports-color - dev: true - - /solidity-docgen@0.6.0-beta.36(hardhat@2.21.0): - resolution: {integrity: sha512-f/I5G2iJgU1h0XrrjRD0hHMr7C10u276vYvm//rw1TzFcYQ4xTOyAoi9oNAHRU0JU4mY9eTuxdVc2zahdMuhaQ==} - peerDependencies: - hardhat: ^2.8.0 - dependencies: - handlebars: 4.7.8 - hardhat: 2.21.0(ts-node@10.9.2)(typescript@5.4.2) - solidity-ast: 0.4.55 - dev: true - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map@0.2.0: - resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} - engines: {node: '>=0.8.0'} - requiresBuild: true + source-map@0.2.0: dependencies: amdefine: 1.0.1 - dev: true optional: true - /source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true + source-map@0.5.7: {} - /stacktrace-parser@0.1.10: - resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} - engines: {node: '>=6'} - dependencies: - type-fest: 0.7.1 - dev: true + source-map@0.6.1: {} - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true + sprintf-js@1.0.3: {} - /string-format@2.0.0: - resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} - dev: true + sprintf-js@1.1.3: + optional: true - /string-width@2.1.1: - resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} - engines: {node: '>=4'} + sqlite3@5.1.7: dependencies: - is-fullwidth-code-point: 2.0.0 - strip-ansi: 4.0.0 - dev: true + bindings: 1.5.0 + node-addon-api: 7.1.1 + prebuild-install: 7.1.2 + tar: 6.2.1 + optionalDependencies: + node-gyp: 8.4.1 + transitivePeerDependencies: + - bluebird + - supports-color - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + ssri@8.0.1: dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true + minipass: 3.3.6 + optional: true - /string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} + stacktrace-parser@0.1.10: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - dev: true + type-fest: 0.7.1 + + statuses@2.0.1: {} + + string-format@2.0.0: {} - /string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string-width@2.1.1: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - dev: true + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 - /string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string-width@4.2.3: dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.22.5 - dev: true + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 - dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - dev: true - /strip-ansi@4.0.0: - resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} - engines: {node: '>=4'} + strip-ansi@4.0.0: dependencies: ansi-regex: 3.0.1 - dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: true - /strip-hex-prefix@1.0.0: - resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} - engines: {node: '>=6.5.0', npm: '>=3'} + strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed: 1.0.0 - dev: true - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true + strip-json-comments@2.0.1: {} - /supports-color@3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} + strip-json-comments@3.1.1: {} + + supports-color@3.2.3: dependencies: has-flag: 1.0.0 - dev: true - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - dev: true - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + supports-color@8.1.1: dependencies: has-flag: 4.0.0 - dev: true - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true + supports-preserve-symlinks-flag@1.0.0: {} - /sync-request@6.1.0: - resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} - engines: {node: '>=8.0.0'} + sync-request@6.1.0: dependencies: http-response-object: 3.0.2 sync-rpc: 1.3.6 then-request: 6.0.2 - dev: true - /sync-rpc@1.3.6: - resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} + sync-rpc@1.3.6: dependencies: get-port: 3.2.0 - dev: true - /table-layout@1.0.2: - resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} - engines: {node: '>=8.0.0'} + table-layout@1.0.2: dependencies: array-back: 4.0.2 deep-extend: 0.6.0 typical: 5.2.0 wordwrapjs: 4.0.1 - dev: true - /table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} + table@6.8.1: dependencies: ajv: 8.12.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true + tar-fs@2.1.1: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.2 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 - /tfhe@0.5.3: - resolution: {integrity: sha512-LrZXKPzI/YsLwJA+y41uYvQU+G1/JbXea30eQXXFdLSeYPPO45a9jCL5ZqvkWZkRFA9Ox2/7t86+1ysR/1DNyw==} - dev: true + text-table@0.2.0: {} - /then-request@6.0.2: - resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} - engines: {node: '>=6.0.0'} + tfhe@0.8.6: {} + + then-request@6.0.2: dependencies: '@types/concat-stream': 1.6.1 '@types/form-data': 0.0.33 @@ -5134,57 +6906,37 @@ packages: http-response-object: 3.0.2 promise: 8.3.0 qs: 6.12.0 - dev: true - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} + tkms@0.9.0-rc3: {} + + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 - dev: true - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true + to-fast-properties@2.0.0: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true + toidentifier@1.0.1: {} - /ts-command-line-args@2.5.1: - resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} - hasBin: true + tr46@0.0.3: {} + + ts-command-line-args@2.5.1: dependencies: chalk: 4.1.2 command-line-args: 5.2.1 command-line-usage: 6.1.3 string-format: 2.0.0 - dev: true - /ts-essentials@1.0.4: - resolution: {integrity: sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==} - dev: true + ts-essentials@1.0.4: {} - /ts-essentials@7.0.3(typescript@5.4.2): - resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} - peerDependencies: - typescript: '>=3.7.0' + ts-essentials@7.0.3(typescript@5.4.2): dependencies: typescript: 5.4.2 - dev: true - /ts-generator@0.1.1: - resolution: {integrity: sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==} - hasBin: true + ts-generator@0.1.1: dependencies: '@types/mkdirp': 0.5.2 '@types/prettier': 2.7.3 @@ -5195,28 +6947,15 @@ packages: prettier: 2.8.8 resolve: 1.22.8 ts-essentials: 1.0.4 - dev: true - /ts-node@10.9.2(@types/node@18.19.23)(typescript@5.4.2): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + ts-node@10.9.2(@types/node@18.19.59)(typescript@5.4.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.23 + '@types/node': 18.19.59 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 @@ -5226,77 +6965,45 @@ packages: typescript: 5.4.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true + tslib@1.14.1: {} - /tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - dev: true + tslib@2.4.0: {} - /tsort@0.0.1: - resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - dev: true + tslib@2.8.0: {} - /tsutils@3.21.0(typescript@5.4.2): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + tsort@0.0.1: {} + + tsutils@3.21.0(typescript@5.4.2): dependencies: tslib: 1.14.1 typescript: 5.4.2 - dev: true - /tweetnacl-util@0.15.1: - resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} - dev: true + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 - /tweetnacl@1.0.3: - resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} - dev: true + tweetnacl-util@0.15.1: {} - /type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} + tweetnacl@1.0.3: {} + + type-check@0.3.2: dependencies: prelude-ls: 1.1.2 - dev: true - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - dev: true - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true + type-detect@4.0.8: {} - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true + type-fest@0.20.2: {} - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true + type-fest@0.21.3: {} - /type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - dev: true + type-fest@0.7.1: {} - /typechain@8.3.2(typescript@5.4.2): - resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} - hasBin: true - peerDependencies: - typescript: '>=4.3.0' + typechain@8.3.2(typescript@5.4.2): dependencies: '@types/prettier': 2.7.3 debug: 4.3.4(supports-color@8.1.1) @@ -5311,141 +7018,76 @@ packages: typescript: 5.4.2 transitivePeerDependencies: - supports-color - dev: true - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true + typedarray@0.0.6: {} - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true + typescript@5.4.2: {} - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true + typical@4.0.0: {} - /typed-array-length@1.0.5: - resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true + typical@5.2.0: {} - /typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - dev: true + uglify-js@3.17.4: + optional: true - /typescript@5.4.2: - resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} - engines: {node: '>=14.17'} - hasBin: true - dev: true + undici-types@5.26.5: {} - /typical@4.0.0: - resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} - engines: {node: '>=8'} - dev: true + undici@5.28.3: + dependencies: + '@fastify/busboy': 2.1.1 - /typical@5.2.0: - resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} - engines: {node: '>=8'} - dev: true + undici@6.20.1: {} - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true + unfetch@4.2.0: {} + + unique-filename@1.1.1: + dependencies: + unique-slug: 2.0.2 optional: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unique-slug@2.0.2: dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true + imurmurhash: 0.1.4 + optional: true - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true + universalify@0.1.2: {} - /undici@5.28.3: - resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==} - engines: {node: '>=14.0'} + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + uri-js@4.4.1: dependencies: - '@fastify/busboy': 2.1.1 - dev: true + punycode: 2.3.1 - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.13.0 - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true + utf8@3.0.0: {} - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true + util-deprecate@1.0.2: {} - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + util@0.12.5: dependencies: - punycode: 2.3.1 - dev: true + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 - /utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - dev: true + uuid@8.3.2: {} - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true + v8-compile-cache-lib@3.0.1: {} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true + web3-errors@1.3.0: + dependencies: + web3-types: 1.8.1 - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true + web3-types@1.8.1: {} - /web3-utils@1.10.4: - resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} - engines: {node: '>=8.0.0'} + web3-utils@1.10.4: dependencies: '@ethereumjs/util': 8.1.0 bn.js: 5.2.1 @@ -5455,151 +7097,86 @@ packages: number-to-bn: 1.7.0 randombytes: 2.1.0 utf8: 3.0.0 - dev: true - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + web3-validator@2.0.6: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true + ethereum-cryptography: 2.1.3 + util: 0.12.5 + web3-errors: 1.3.0 + web3-types: 1.8.1 + zod: 3.23.8 - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.2 - dev: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + which@1.3.1: dependencies: isexe: 2.0.0 - dev: true - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} + wide-align@1.1.5: dependencies: string-width: 4.2.3 - dev: true + optional: true - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true + widest-line@3.1.0: + dependencies: + string-width: 4.2.3 - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true + word-wrap@1.2.5: {} - /wordwrapjs@4.0.1: - resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} - engines: {node: '>=8.0.0'} + wordwrap@1.0.0: {} + + wordwrapjs@4.0.1: dependencies: reduce-flatten: 2.0.0 typical: 5.2.0 - dev: true - /workerpool@6.2.1: - resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} - dev: true + workerpool@6.2.1: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true + wrappy@1.0.2: {} - /ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@7.4.6: {} - /ws@7.5.9: - resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@7.5.9: {} - /ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@8.5.0: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yallist@4.0.0: {} - /yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - dev: true + yargs-parser@20.2.4: {} - /yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} + yargs-unparser@2.0.0: dependencies: camelcase: 6.3.0 decamelize: 4.0.0 flat: 5.0.2 is-plain-obj: 2.1.0 - dev: true - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + yargs@16.2.0: dependencies: cliui: 7.0.4 escalade: 3.1.2 @@ -5608,23 +7185,13 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 20.2.4 - dev: true - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true + yn@3.1.1: {} - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} - /zksync-web3@0.14.4(ethers@5.7.2): - resolution: {integrity: sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg==} - deprecated: This package has been deprecated in favor of zksync-ethers@5.0.0 - peerDependencies: - ethers: ^5.7.0 + zksync-web3@0.14.4(ethers@5.7.2): dependencies: ethers: 5.7.2 - dev: true + + zod@3.23.8: {} diff --git a/remappings.txt b/remappings.txt deleted file mode 100644 index 038a557..0000000 --- a/remappings.txt +++ /dev/null @@ -1 +0,0 @@ -lib/TFHE=mocks/TFHE \ No newline at end of file diff --git a/tasks/accounts.ts b/tasks/accounts.ts index 866b83a..b206222 100644 --- a/tasks/accounts.ts +++ b/tasks/accounts.ts @@ -1,9 +1,9 @@ import { task } from "hardhat/config"; -task("task:accounts", "Prints the list of accounts", async (_taskArgs, hre) => { +task("accounts", "Prints the list of accounts", async (_taskArgs, hre) => { const accounts = await hre.ethers.getSigners(); for (const account of accounts) { - console.log(account.address); + console.info(account.address); } }); diff --git a/tasks/taskDeploy.ts b/tasks/taskDeploy.ts new file mode 100644 index 0000000..f7395ce --- /dev/null +++ b/tasks/taskDeploy.ts @@ -0,0 +1,156 @@ +import dotenv from "dotenv"; +import fs from "fs"; +import { task, types } from "hardhat/config"; +import type { TaskArguments } from "hardhat/types"; + +task("task:deployGateway") + .addParam("privateKey", "The deployer private key") + .addParam("ownerAddress", "The owner address") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory("GatewayContract", deployer); + const Gateway = await upgrades.deployProxy(factory, [taskArguments.ownerAddress], { + initializer: "initialize", + kind: "uups", + }); + await Gateway.waitForDeployment(); + const GatewayContractAddress = await Gateway.getAddress(); + const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm/gateway/.env.gateway")); + if (GatewayContractAddress !== envConfig.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not null. Please use another deployer private key or relaunch a clean instance of the fhEVM`, + ); + } + console.log("GatewayContract was deployed at address: ", GatewayContractAddress); + }); + +task("task:deployACL") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory("fhevmTemp/contracts/ACL.sol:ACL", deployer); + const acl = await upgrades.deployProxy(factory, [deployer.address], { initializer: "initialize", kind: "uups" }); + await acl.waitForDeployment(); + const address = await acl.getAddress(); + const envConfigAcl = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl")); + if (address !== envConfigAcl.ACL_CONTRACT_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, + ); + } + console.log("ACL was deployed at address:", address); + }); + +task("task:deployTFHEExecutor") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory( + "fhevmTemp/contracts/TFHEExecutor.events.sol:TFHEExecutor", + deployer, + ); + const exec = await upgrades.deployProxy(factory, [deployer.address], { initializer: "initialize", kind: "uups" }); + await exec.waitForDeployment(); + const address = await exec.getAddress(); + const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.exec")); + if (address !== envConfig.TFHE_EXECUTOR_CONTRACT_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, + ); + } + console.log("TFHEExecutor was deployed at address:", address); + }); + +task("task:deployKMSVerifier") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory("fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier", deployer); + const kms = await upgrades.deployProxy(factory, [deployer.address], { initializer: "initialize", kind: "uups" }); + await kms.waitForDeployment(); + const address = await kms.getAddress(); + const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.kmsverifier")); + if (address !== envConfig.KMS_VERIFIER_CONTRACT_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, + ); + } + console.log("KMSVerifier was deployed at address:", address); + }); + +task("task:deployInputVerifier") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + let factory; + if (process.env.IS_COPROCESSOR === "true") { + factory = await ethers.getContractFactory( + "fhevmTemp/contracts/InputVerifier.coprocessor.sol:InputVerifier", + deployer, + ); + } else { + factory = await ethers.getContractFactory("fhevmTemp/contracts/InputVerifier.native.sol:InputVerifier", deployer); + } + const kms = await upgrades.deployProxy(factory, [deployer.address], { initializer: "initialize", kind: "uups" }); + await kms.waitForDeployment(); + const address = await kms.getAddress(); + const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.inputverifier")); + if (address !== envConfig.INPUT_VERIFIER_CONTRACT_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, + ); + } + console.log("InputVerifier was deployed at address:", address); + }); + +task("task:deployFHEPayment") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory("fhevmTemp/contracts/FHEPayment.sol:FHEPayment", deployer); + const payment = await upgrades.deployProxy(factory, [deployer.address], { + initializer: "initialize", + kind: "uups", + }); + await payment.waitForDeployment(); + const address = await payment.getAddress(); + const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.fhepayment")); + if (address !== envConfig.FHE_PAYMENT_CONTRACT_ADDRESS) { + throw new Error( + `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, + ); + } + console.log("FHEPayment was deployed at address:", address); + }); + +task("task:addSigners") + .addParam("privateKey", "The deployer private key") + .addParam("numSigners", "Number of KMS signers to add") + .addOptionalParam( + "useAddress", + "Use addresses instead of private keys env variables for kms signers", + false, + types.boolean, + ) + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory("fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier", deployer); + const kmsAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.kmsverifier"), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + const kmsVerifier = await factory.attach(kmsAdd); + for (let idx = 0; idx < taskArguments.numSigners; idx++) { + if (!taskArguments.useAddress) { + const privKeySigner = process.env[`PRIVATE_KEY_KMS_SIGNER_${idx}`]; + const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); + const tx = await kmsVerifier.addSigner(kmsSigner.address); + await tx.wait(); + console.log(`KMS signer no${idx} (${kmsSigner.address}) was added to KMSVerifier contract`); + } else { + const kmsSignerAddress = process.env[`ADDRESS_KMS_SIGNER_${idx}`]; + const tx = await kmsVerifier.addSigner(kmsSignerAddress); + await tx.wait(); + console.log(`KMS signer no${idx} (${kmsSignerAddress}) was added to KMSVerifier contract`); + } + } + }); diff --git a/tasks/taskGatewayRelayer.ts b/tasks/taskGatewayRelayer.ts new file mode 100644 index 0000000..581d508 --- /dev/null +++ b/tasks/taskGatewayRelayer.ts @@ -0,0 +1,166 @@ +import { exec as oldExec } from "child_process"; +import dotenv from "dotenv"; +import fs from "fs"; +import { task, types } from "hardhat/config"; +import type { TaskArguments } from "hardhat/types"; +import path from "path"; +import { promisify } from "util"; + +const exec = promisify(oldExec); + +const getCoin = async (address: string) => { + const containerName = process.env["TEST_CONTAINER_NAME"] || "fhevm"; + const response = await exec(`docker exec -i ${containerName} faucet ${address} | grep height`); + const res = JSON.parse(response.stdout); + if (res.raw_log.match("account sequence mismatch")) await getCoin(address); +}; + +task("task:computeGatewayAddress") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployerAddress = new ethers.Wallet(taskArguments.privateKey).address; + const gatewayContractAddressPrecomputed = ethers.getCreateAddress({ + from: deployerAddress, + nonce: 1, // deployer is supposed to have nonce 0 when deploying GatewayContract (0 nonce for implementation, +1 for UUPS) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm/gateway/.env.gateway"); + const content = `GATEWAY_CONTRACT_PREDEPLOY_ADDRESS=${gatewayContractAddressPrecomputed}`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log("gatewayContractAddress written to node_modules/fhevm/gateway/.env.gateway successfully!"); + } catch (err) { + console.error("Failed to write to node_modules/fhevm/gateway/.env.gateway:", err); + } + + const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant GATEWAY_CONTRACT_PREDEPLOY_ADDRESS = ${gatewayContractAddressPrecomputed}; +`; + + try { + fs.writeFileSync("./node_modules/fhevm/gateway/lib/GatewayContractAddress.sol", solidityTemplate, { + encoding: "utf8", + flag: "w", + }); + console.log("node_modules/fhevm/gateway/lib/GatewayContractAddress.sol file has been generated successfully."); + } catch (error) { + console.error("Failed to write node_modules/fhevm/gateway/lib/GatewayContractAddress.sol", error); + } + }); + +task("task:addRelayer") + .addParam("privateKey", "The owner private key") + .addParam("gatewayAddress", "The GatewayContract address") + .addParam("relayerAddress", "The relayer address") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const codeAtAddress = await ethers.provider.getCode(taskArguments.gatewayAddress); + if (codeAtAddress === "0x") { + throw Error(`${taskArguments.gatewayAddress} is not a smart contract`); + } + const owner = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const gateway = await ethers.getContractAt("GatewayContract", taskArguments.gatewayAddress, owner); + const tx = await gateway.addRelayer(taskArguments.relayerAddress); + const rcpt = await tx.wait(); + if (rcpt!.status === 1) { + console.log(`Account ${taskArguments.relayerAddress} was succesfully added as an gateway relayer`); + } else { + console.log("Adding relayer failed"); + } + }); + +task("task:removeRelayer") + .addParam("privateKey", "The owner private key") + .addParam("gatewayAddress", "The GatewayContract address") + .addParam("relayerAddress", "The relayer address") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const codeAtAddress = await ethers.provider.getCode(taskArguments.gatewayAddress); + if (codeAtAddress === "0x") { + throw Error(`${taskArguments.gatewayAddress} is not a smart contract`); + } + const owner = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const gateway = await ethers.getContractAt("GatewayContract", taskArguments.gatewayAddress, owner); + const tx = await gateway.removeRelayer(taskArguments.relayerAddress); + const rcpt = await tx.wait(); + if (rcpt!.status === 1) { + console.log(`Account ${taskArguments.relayerAddress} was succesfully removed from authorized relayers`); + } else { + console.log("Removing relayer failed"); + } + }); + +task("task:launchFhevm") + .addOptionalParam("skipGetCoin", "Skip calling getCoin()", false, types.boolean) + .addOptionalParam("useAddress", "Use address instead of privte key for the Gateway Relayer", false, types.boolean) + .setAction(async function (taskArgs, hre) { + const privKeyDeployer = process.env.PRIVATE_KEY_GATEWAY_DEPLOYER; + const deployerAddress = new hre.ethers.Wallet(privKeyDeployer!).address; + let relayerAddress; + if (!taskArgs.useAddress) { + const privKeyRelayer = process.env.PRIVATE_KEY_GATEWAY_RELAYER; + relayerAddress = new hre.ethers.Wallet(privKeyRelayer!).address; + } else { + relayerAddress = process.env.ADDRESS_GATEWAY_RELAYER; + } + if (!taskArgs.skipGetCoin) { + if (hre.network.name === "hardhat") { + const bal = "0x1000000000000000000000000000000000000000"; + const p1 = hre.network.provider.send("hardhat_setBalance", [deployerAddress, bal]); + const p2 = hre.network.provider.send("hardhat_setBalance", [relayerAddress, bal]); + await Promise.all([p1, p2]); + } else { + const p1 = getCoin(deployerAddress); + const p2 = getCoin(relayerAddress); + await Promise.all([p1, p2]); + await new Promise((res) => setTimeout(res, 5000)); // wait 5 seconds + } + } + await hre.run("task:deployGateway", { privateKey: privKeyDeployer, ownerAddress: deployerAddress }); + + const parsedEnv = dotenv.parse(fs.readFileSync("node_modules/fhevm/gateway/.env.gateway")); + const gatewayContractAddress = parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS; + + await hre.run("task:addRelayer", { + privateKey: privKeyDeployer, + gatewayAddress: gatewayContractAddress, + relayerAddress: relayerAddress, + }); + }); + +task("task:getBalances").setAction(async function (taskArgs, hre) { + const privKeyDeployer = process.env.PRIVATE_KEY_GATEWAY_DEPLOYER; + const privKeyRelayer = process.env.PRIVATE_KEY_GATEWAY_RELAYER; + const deployerAddress = new hre.ethers.Wallet(privKeyDeployer!).address; + const relayerAddress = new hre.ethers.Wallet(privKeyRelayer!).address; + console.log(await hre.ethers.provider.getBalance(deployerAddress)); + console.log(await hre.ethers.provider.getBalance(relayerAddress)); +}); + +task("task:faucetToPrivate") + .addParam("privateKey", "The receiver private key") + .setAction(async function (taskArgs, hre) { + const receiverAddress = new hre.ethers.Wallet(taskArgs.privateKey).address; + + if (hre.network.name === "hardhat") { + const bal = "0x1000000000000000000000000000000000000000"; + await hre.network.provider.send("hardhat_setBalance", [receiverAddress, bal]); + } else { + await getCoin(receiverAddress); + await new Promise((res) => setTimeout(res, 5000)); // wait 5 seconds + } + }); + +task("task:faucetToAddress") + .addParam("address", "The receiver address") + .setAction(async function (taskArgs, hre) { + const receiverAddress = taskArgs.address; + + if (hre.network.name === "hardhat") { + const bal = "0x1000000000000000000000000000000000000000"; + await hre.network.provider.send("hardhat_setBalance", [receiverAddress, bal]); + } else { + await getCoin(receiverAddress); + await new Promise((res) => setTimeout(res, 5000)); // wait 5 seconds + } + }); diff --git a/tasks/taskOracleRelayer.ts b/tasks/taskOracleRelayer.ts deleted file mode 100644 index f20472c..0000000 --- a/tasks/taskOracleRelayer.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { exec as oldExec } from "child_process"; -import dotenv from "dotenv"; -import fs from "fs"; -import { task } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; -import path from "path"; -import { promisify } from "util"; - -const exec = promisify(oldExec); - -task("task:deployOracle") - .addParam("privateKey", "The deployer private key") - .addParam("ownerAddress", "The owner address") - .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const oracleFactory = await ethers.getContractFactory("OraclePredeploy"); - const oracle = await oracleFactory.connect(deployer).deploy(taskArguments.ownerAddress); - await oracle.waitForDeployment(); - const oraclePredeployAddress = await oracle.getAddress(); - const envConfig = dotenv.parse(fs.readFileSync("node_modules/fhevm/oracle/.env.oracle")); - if (oraclePredeployAddress !== envConfig.ORACLE_CONTRACT_PREDEPLOY_ADDRESS) { - throw new Error( - `The nonce of the deployer account is not null. Please use another deployer private key or relaunch a clean instance of the fhEVM`, - ); - } - console.log("OraclePredeploy was deployed at address: ", oraclePredeployAddress); - }); - -const getCoin = async (address: string) => { - const containerName = process.env["TEST_CONTAINER_NAME"] || "fhevm"; - const response = await exec(`docker exec -i ${containerName} faucet ${address} | grep height`); - const res = JSON.parse(response.stdout); - if (res.raw_log.match("account sequence mismatch")) await getCoin(address); -}; - -task("task:computePredeployAddress") - .addParam("privateKey", "The deployer private key") - .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const deployerAddress = new ethers.Wallet(taskArguments.privateKey).address; - const oraclePredeployAddressPrecomputed = ethers.getCreateAddress({ - from: deployerAddress, - nonce: 0, // deployer is supposed to have nonce 0 when deploying OraclePredeploy - }); - const envFilePath = path.join(__dirname, "../node_modules/fhevm/oracle/.env.oracle"); - const content = `ORACLE_CONTRACT_PREDEPLOY_ADDRESS=${oraclePredeployAddressPrecomputed}\n`; - try { - fs.writeFileSync(envFilePath, content, { flag: "w" }); - console.log("oraclePredeployAddress written to node_modules/fhevm/oracle/.env.oracle successfully!"); - } catch (err) { - console.error("Failed to write to node_modules/fhevm/oracle/.env.oracle:", err); - } - - const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.20; - -address constant ORACLE_CONTRACT_PREDEPLOY_ADDRESS = ${oraclePredeployAddressPrecomputed}; - `; - - try { - fs.writeFileSync("./node_modules/fhevm/oracle/lib/PredeployAddress.sol", solidityTemplate, { - encoding: "utf8", - flag: "w", - }); - console.log("node_modules/fhevm/oracle/lib/PredeployAddress.sol file has been generated successfully."); - } catch (error) { - console.error("Failed to write node_modules/fhevm/oracle/lib/PredeployAddress.sol", error); - } - }); - -task("task:addRelayer") - .addParam("privateKey", "The owner private key") - .addParam("oracleAddress", "The OraclePredeploy address") - .addParam("relayerAddress", "The relayer address") - .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const codeAtAddress = await ethers.provider.getCode(taskArguments.oracleAddress); - if (codeAtAddress === "0x") { - throw Error(`${taskArguments.oracleAddress} is not a smart contract`); - } - const owner = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const oracle = await ethers.getContractAt("OraclePredeploy", taskArguments.oracleAddress, owner); - const tx = await oracle.addRelayer(taskArguments.relayerAddress); - const rcpt = await tx.wait(); - if (rcpt!.status === 1) { - console.log(`Account ${taskArguments.relayerAddress} was succesfully added as an oracle relayer`); - } else { - console.log("Adding relayer failed"); - } - }); - -task("task:removeRelayer") - .addParam("privateKey", "The owner private key") - .addParam("oracleAddress", "The OraclePredeploy address") - .addParam("relayerAddress", "The relayer address") - .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const codeAtAddress = await ethers.provider.getCode(taskArguments.oracleAddress); - if (codeAtAddress === "0x") { - throw Error(`${taskArguments.oracleAddress} is not a smart contract`); - } - const owner = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const oracle = await ethers.getContractAt("OraclePredeploy", taskArguments.oracleAddress, owner); - const tx = await oracle.removeRelayer(taskArguments.relayerAddress); - const rcpt = await tx.wait(); - if (rcpt!.status === 1) { - console.log(`Account ${taskArguments.relayerAddress} was succesfully removed from authorized relayers`); - } else { - console.log("Removing relayer failed"); - } - }); - -task("task:launchFhevm").setAction(async function (taskArgs, hre) { - const privKeyDeployer = process.env.PRIVATE_KEY_ORACLE_DEPLOYER; - const privKeyOwner = process.env.PRIVATE_KEY_ORACLE_OWNER; - const privKeyRelayer = process.env.PRIVATE_KEY_ORACLE_RELAYER; - const deployerAddress = new hre.ethers.Wallet(privKeyDeployer!).address; - const ownerAddress = new hre.ethers.Wallet(privKeyOwner!).address; - const relayerAddress = new hre.ethers.Wallet(privKeyRelayer!).address; - const p1 = getCoin(deployerAddress); - const p2 = getCoin(ownerAddress); - const p3 = getCoin(relayerAddress); - await Promise.all([p1, p2, p3]); - await new Promise((res) => setTimeout(res, 5000)); // wait 5 seconds - await hre.run("task:deployOracle", { privateKey: privKeyDeployer, ownerAddress: ownerAddress }); - - const parsedEnv = dotenv.parse(fs.readFileSync("node_modules/fhevm/oracle/.env.oracle")); - const oraclePredeployAddress = parsedEnv.ORACLE_CONTRACT_PREDEPLOY_ADDRESS; - - await hre.run("task:addRelayer", { - privateKey: privKeyOwner, - oracleAddress: oraclePredeployAddress, - relayerAddress: relayerAddress, - }); -}); - -task("task:getBalances").setAction(async function (taskArgs, hre) { - const privKeyDeployer = process.env.PRIVATE_KEY_ORACLE_DEPLOYER; - const privKeyOwner = process.env.PRIVATE_KEY_ORACLE_OWNER; - const privKeyRelayer = process.env.PRIVATE_KEY_ORACLE_RELAYER; - const deployerAddress = new hre.ethers.Wallet(privKeyDeployer!).address; - const ownerAddress = new hre.ethers.Wallet(privKeyOwner!).address; - const relayerAddress = new hre.ethers.Wallet(privKeyRelayer!).address; - console.log(await hre.ethers.provider.getBalance(deployerAddress)); - console.log(await hre.ethers.provider.getBalance(ownerAddress)); - console.log(await hre.ethers.provider.getBalance(relayerAddress)); -}); diff --git a/tasks/taskTFHE.ts b/tasks/taskTFHE.ts new file mode 100644 index 0000000..e5c3e37 --- /dev/null +++ b/tasks/taskTFHE.ts @@ -0,0 +1,214 @@ +import fs from "fs"; +import { task, types } from "hardhat/config"; +import type { TaskArguments } from "hardhat/types"; +import path from "path"; + +task("task:computeACLAddress") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).address; + const aclAddress = ethers.getCreateAddress({ + from: deployer, + nonce: 1, // using nonce of 1 for the ACL contract (0 for original implementation, +1 for proxy) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.acl"); + const content = `ACL_CONTRACT_ADDRESS=${aclAddress}\n`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log(`ACL address ${aclAddress} written successfully!`); + } catch (err) { + console.error("Failed to write ACL address:", err); + } + + const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant aclAdd = ${aclAddress};\n`; + + try { + fs.writeFileSync("./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol", solidityTemplate, { + encoding: "utf8", + flag: "w", + }); + console.log("./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol file generated successfully!"); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol", error); + } + }); + +task("task:computeTFHEExecutorAddress") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).address; + const execAddress = ethers.getCreateAddress({ + from: deployer, + nonce: 3, // using nonce of 3 for the TFHEExecutor contract (2 for original implementation, +1 for proxy) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.exec"); + const content = `TFHE_EXECUTOR_CONTRACT_ADDRESS=${execAddress}\n`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log(`TFHEExecutor address ${execAddress} written successfully!`); + } catch (err) { + console.error("Failed to write TFHEExecutor address:", err); + } + + const solidityTemplateCoprocessor = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant tfheExecutorAdd = ${execAddress};\n`; + + try { + fs.writeFileSync( + "./node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol", + solidityTemplateCoprocessor, + { encoding: "utf8", flag: "w" }, + ); + console.log("./node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol file generated successfully!"); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol", error); + } + }); + +task("task:computeKMSVerifierAddress") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).address; + const kmsVerfierAddress = ethers.getCreateAddress({ + from: deployer, + nonce: 5, // using nonce of 5 for the KMSVerifier contract (4 for original implementation, +1 for proxy) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.kmsverifier"); + const content = `KMS_VERIFIER_CONTRACT_ADDRESS=${kmsVerfierAddress}\n`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log(`KMSVerifier address ${kmsVerfierAddress} written successfully!`); + } catch (err) { + console.error("Failed to write KMSVerifier address:", err); + } + + const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant kmsVerifierAdd = ${kmsVerfierAddress};\n`; + + try { + fs.writeFileSync("./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol", solidityTemplate, { + encoding: "utf8", + flag: "w", + }); + console.log("./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol file generated successfully!"); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol", error); + } + }); + +task("task:computeInputVerifierAddress") + .addParam("privateKey", "The deployer private key") + .addOptionalParam( + "useAddress", + "Use addresses instead of private key env variable for coprocessor", + false, + types.boolean, + ) + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + // this script also compute the coprocessor address from its private key + const deployer = new ethers.Wallet(taskArguments.privateKey).address; + const inputVerfierAddress = ethers.getCreateAddress({ + from: deployer, + nonce: 7, // using nonce of 7 for the InputVerifier contract (6 for original implementation, +1 for proxy) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.inputverifier"); + const content = `INPUT_VERIFIER_CONTRACT_ADDRESS=${inputVerfierAddress}\n`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log(`InputVerifier address ${inputVerfierAddress} written successfully!`); + } catch (err) { + console.error("Failed to write InputVerifier address:", err); + } + + const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant inputVerifierAdd = ${inputVerfierAddress};\n`; + + try { + fs.writeFileSync("./node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol", solidityTemplate, { + encoding: "utf8", + flag: "w", + }); + console.log( + "./node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol file generated successfully!", + ); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol", error); + } + let coprocAddress; + if (!taskArguments.useAddress) { + coprocAddress = new ethers.Wallet(process.env.PRIVATE_KEY_COPROCESSOR_ACCOUNT!).address; + } else { + coprocAddress = process.env.ADDRESS_COPROCESSOR_ACCOUNT; + } + const envFilePath2 = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.coprocessor"); + const content2 = `COPROCESSOR_ADDRESS=${coprocAddress}\n`; + try { + fs.writeFileSync(envFilePath2, content2, { flag: "w" }); + console.log(`Coprocessor address ${coprocAddress} written successfully!`); + } catch (err) { + console.error("Failed to write InputVerifier address:", err); + } + + const solidityTemplate2 = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant coprocessorAdd = ${coprocAddress};\n`; + + try { + fs.writeFileSync("./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol", solidityTemplate2, { + encoding: "utf8", + flag: "w", + }); + console.log("./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol file generated successfully!"); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol", error); + } + }); + +task("task:computeFHEPaymentAddress") + .addParam("privateKey", "The deployer private key") + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).address; + const fhePaymentAddress = ethers.getCreateAddress({ + from: deployer, + nonce: 9, // using nonce of 9 for the FHEPayment contract (8 for original implementation, +1 for proxy) + }); + const envFilePath = path.join(__dirname, "../node_modules/fhevm-core-contracts/addresses/.env.fhepayment"); + const content = `FHE_PAYMENT_CONTRACT_ADDRESS=${fhePaymentAddress}\n`; + try { + fs.writeFileSync(envFilePath, content, { flag: "w" }); + console.log(`FHEPayment address ${fhePaymentAddress} written successfully!`); + } catch (err) { + console.error("Failed to write FHEPayment address:", err); + } + + const solidityTemplate = `// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +address constant fhePaymentAdd = ${fhePaymentAddress};\n`; + + try { + fs.writeFileSync("./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol", solidityTemplate, { + encoding: "utf8", + flag: "w", + }); + console.log("./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol file generated successfully!"); + } catch (error) { + console.error("Failed to write ./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol", error); + } + }); diff --git a/test/asyncDecrypt.ts b/test/asyncDecrypt.ts index bee5804..b683543 100644 --- a/test/asyncDecrypt.ts +++ b/test/asyncDecrypt.ts @@ -1,408 +1,243 @@ import dotenv from "dotenv"; +import { Wallet } from "ethers"; import fs from "fs"; -import { ethers } from "hardhat"; +import { ethers, network } from "hardhat"; -import { OraclePredeploy } from "../../types"; +import { GatewayContract } from "../types"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; import { waitNBlocks } from "./utils"; -const network = process.env.HARDHAT_NETWORK; +const networkName = network.name; + +const parsedEnvACL = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl")); +const aclAdd = parsedEnvACL.ACL_CONTRACT_ADDRESS; + +const CiphertextType = { + 0: "bool", + 1: "uint8", // corresponding to euint4 + 2: "uint8", // corresponding to euint8 + 3: "uint16", + 4: "uint32", + 5: "uint64", + 6: "uint128", + 7: "address", + 8: "uint256", + 9: "bytes", + 10: "bytes", + 11: "bytes", +}; const currentTime = (): string => { const now = new Date(); return now.toLocaleTimeString("en-US", { hour12: true, hour: "numeric", minute: "numeric", second: "numeric" }); }; -const parsedEnv = dotenv.parse(fs.readFileSync("node_modules/fhevm/oracle/.env.oracle")); -const privKeyRelayer = process.env.PRIVATE_KEY_ORACLE_RELAYER; -const relayer = new ethers.Wallet(privKeyRelayer!, ethers.provider); +const parsedEnv = dotenv.parse(fs.readFileSync("node_modules/fhevm/gateway/.env.gateway")); +let relayer: Wallet; +if (networkName === "hardhat") { + const privKeyRelayer = process.env.PRIVATE_KEY_GATEWAY_RELAYER; + relayer = new ethers.Wallet(privKeyRelayer!, ethers.provider); +} const argEvents = - "(uint256 indexed requestID, uint256[] cts, address contractCaller, bytes4 callbackSelector, uint256 msgValue, uint256 maxTimestamp)"; -const ifaceEventDecryptionEBool = new ethers.Interface(["event EventDecryptionEBool" + argEvents]); -const ifaceEventDecryptionEUint4 = new ethers.Interface(["event EventDecryptionEUint4" + argEvents]); -const ifaceEventDecryptionEUint8 = new ethers.Interface(["event EventDecryptionEUint8" + argEvents]); -const ifaceEventDecryptionEUint16 = new ethers.Interface(["event EventDecryptionEUint16" + argEvents]); -const ifaceEventDecryptionEUint32 = new ethers.Interface(["event EventDecryptionEUint32" + argEvents]); -const ifaceEventDecryptionEUint64 = new ethers.Interface(["event EventDecryptionEUint64" + argEvents]); -const ifaceEventDecryptionEAddress = new ethers.Interface(["event EventDecryptionEAddress" + argEvents]); + "(uint256 indexed requestID, uint256[] cts, address contractCaller, bytes4 callbackSelector, uint256 msgValue, uint256 maxTimestamp, bool passSignaturesToCaller)"; +const ifaceEventDecryption = new ethers.Interface(["event EventDecryption" + argEvents]); const argEvents2 = "(uint256 indexed requestID, bool success, bytes result)"; -const ifaceResultCallbackBool = new ethers.Interface(["event ResultCallbackBool" + argEvents2]); -const ifaceResultCallbackUint4 = new ethers.Interface(["event ResultCallbackUint4" + argEvents2]); -const ifaceResultCallbackUint8 = new ethers.Interface(["event ResultCallbackUint8" + argEvents2]); -const ifaceResultCallbackUint16 = new ethers.Interface(["event ResultCallbackUint16" + argEvents2]); -const ifaceResultCallbackUint32 = new ethers.Interface(["event ResultCallbackUint32" + argEvents2]); -const ifaceResultCallbackUint64 = new ethers.Interface(["event ResultCallbackUint64" + argEvents2]); -const ifaceResultcallbackAddress = new ethers.Interface(["event ResultcallbackAddress" + argEvents2]); +const ifaceResultCallback = new ethers.Interface(["event ResultCallback" + argEvents2]); -let oracle: OraclePredeploy; +let gateway: GatewayContract; let firstBlockListening: number; +let lastBlockSnapshotForDecrypt: number; -export const asyncDecrypt = async (): Promise => { +export const initGateway = async (): Promise => { firstBlockListening = await ethers.provider.getBlockNumber(); + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await ethers.provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); + } // this function will emit logs for every request and fulfilment of a decryption - oracle = await ethers.getContractAt("OraclePredeploy", parsedEnv.ORACLE_CONTRACT_PREDEPLOY_ADDRESS); - oracle.on( - "EventDecryptionEBool", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Requested ebool decrypt on block ${blockNumber} (requestID ${requestID})`); - }, - ); - oracle.on("ResultCallbackBool", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled ebool decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - oracle.on( - "EventDecryptionEUint4", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Requested euint4 decrypt on block ${blockNumber} (requestID ${requestID})`); - }, - ); - oracle.on("ResultCallbackUint4", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled euint4 decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - oracle.on( - "EventDecryptionEUint8", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Requested euint8 decrypt on block ${blockNumber} (requestID ${requestID})`); - }, - ); - oracle.on("ResultCallbackUint8", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled euint8 decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - oracle.on( - "EventDecryptionEUint16", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log( - `${await currentTime()} - Requested euint16 decrypt on block ${blockNumber} (requestID ${requestID})`, - ); - }, - ); - oracle.on("ResultCallbackUint16", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled euint16 decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - oracle.on( - "EventDecryptionEUint32", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log( - `${await currentTime()} - Requested euint32 decrypt on block ${blockNumber} (requestID ${requestID})`, - ); - }, - ); - oracle.on("ResultCallbackUint32", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled euint32 decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - oracle.on( - "EventDecryptionEUint64", + gateway = await ethers.getContractAt("GatewayContract", parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS); + gateway.on( + "EventDecryption", async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { const blockNumber = eventData.log.blockNumber; - console.log( - `${await currentTime()} - Requested euint64 decrypt on block ${blockNumber} (requestID ${requestID})`, - ); + console.log(`${await currentTime()} - Requested decrypt on block ${blockNumber} (requestID ${requestID})`); }, ); - oracle.on("ResultCallbackUint64", async (requestID, success, result, eventData) => { + gateway.on("ResultCallback", async (requestID, success, result, eventData) => { const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled euint64 decrypt on block ${blockNumber} (requestID ${requestID})`); - }); - - oracle.on( - "EventDecryptionEAddress", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log( - `${await currentTime()} - Requested eaddress decrypt on block ${blockNumber} (requestID ${requestID})`, - ); - }, - ); - oracle.on("ResultcallbackAddress", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled eaddress decrypt on block ${blockNumber} (requestID ${requestID})`); + console.log(`${await currentTime()} - Fulfilled decrypt on block ${blockNumber} (requestID ${requestID})`); }); }; export const awaitAllDecryptionResults = async (): Promise => { - oracle = await ethers.getContractAt("OraclePredeploy", parsedEnv.ORACLE_CONTRACT_PREDEPLOY_ADDRESS); - await fulfillAllPastRequestsIds(network === "hardhat"); - firstBlockListening = await ethers.provider.getBlockNumber(); + gateway = await ethers.getContractAt("GatewayContract", parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS); + const provider = ethers.provider; + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + lastBlockSnapshotForDecrypt = await provider.send("get_lastBlockSnapshotForDecrypt"); + if (lastBlockSnapshotForDecrypt < firstBlockListening) { + firstBlockListening = lastBlockSnapshotForDecrypt + 1; + } + } + await fulfillAllPastRequestsIds(networkName === "hardhat"); + firstBlockListening = (await ethers.provider.getBlockNumber()) + 1; + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); + } }; const getAlreadyFulfilledDecryptions = async (): Promise<[bigint]> => { let results = []; - const eventDecryptionResultBool = await oracle.filters.ResultCallbackBool().getTopicFilter(); - const filterDecryptionResultBool = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultBool, - }; - const pastResultsEbool = await ethers.provider.getLogs(filterDecryptionResultBool); - results = results.concat(pastResultsEbool.map((result) => ifaceResultCallbackBool.parseLog(result).args[0])); - - const eventDecryptionResultEUint4 = await oracle.filters.ResultCallbackUint4().getTopicFilter(); - const filterDecryptionResultUint4 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultEUint4, - }; - const pastResultsEuint4 = await ethers.provider.getLogs(filterDecryptionResultUint4); - results = results.concat(pastResultsEuint4.map((result) => ifaceResultCallbackUint4.parseLog(result).args[0])); - - const eventDecryptionResultEUint8 = await oracle.filters.ResultCallbackUint8().getTopicFilter(); - const filterDecryptionResultUint8 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultEUint8, - }; - const pastResultsEuint8 = await ethers.provider.getLogs(filterDecryptionResultUint8); - results = results.concat(pastResultsEuint8.map((result) => ifaceResultCallbackUint8.parseLog(result).args[0])); - - const eventDecryptionResultEUint16 = await oracle.filters.ResultCallbackUint16().getTopicFilter(); - const filterDecryptionResultUint16 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultEUint16, - }; - const pastResultsEuint16 = await ethers.provider.getLogs(filterDecryptionResultUint16); - results = results.concat(pastResultsEuint16.map((result) => ifaceResultCallbackUint16.parseLog(result).args[0])); - - const eventDecryptionResultEUint32 = await oracle.filters.ResultCallbackUint32().getTopicFilter(); - const filterDecryptionResultUint32 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultEUint32, - }; - const pastResultsEuint32 = await ethers.provider.getLogs(filterDecryptionResultUint32); - results = results.concat(pastResultsEuint32.map((result) => ifaceResultCallbackUint32.parseLog(result).args[0])); - - const eventDecryptionResultEUint64 = await oracle.filters.ResultCallbackUint64().getTopicFilter(); - const filterDecryptionResultUint64 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, + const eventDecryptionResult = await gateway.filters.ResultCallback().getTopicFilter(); + const filterDecryptionResult = { + address: parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS, fromBlock: firstBlockListening, toBlock: "latest", - topics: eventDecryptionResultEUint64, + topics: eventDecryptionResult, }; - const pastResultsEuint64 = await ethers.provider.getLogs(filterDecryptionResultUint64); - results = results.concat(pastResultsEuint64.map((result) => ifaceResultCallbackUint64.parseLog(result).args[0])); - - const eventDecryptionResultEAddress = await oracle.filters.ResultcallbackAddress().getTopicFilter(); - const filterDecryptionResultAddress = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResultEAddress, - }; - const pastResultsEaddress = await ethers.provider.getLogs(filterDecryptionResultAddress); - results = results.concat(pastResultsEaddress.map((result) => ifaceResultcallbackAddress.parseLog(result).args[0])); + const pastResults = await ethers.provider.getLogs(filterDecryptionResult); + results = results.concat(pastResults.map((result) => ifaceResultCallback.parseLog(result).args[0])); return results; }; +const allTrue = (arr: boolean[], fn = Boolean) => arr.every(fn); + const fulfillAllPastRequestsIds = async (mocked: boolean) => { - const eventDecryptionEBool = await oracle.filters.EventDecryptionEBool().getTopicFilter(); + const eventDecryption = await gateway.filters.EventDecryption().getTopicFilter(); const results = await getAlreadyFulfilledDecryptions(); - const filterDecryptionEBool = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, + const filterDecryption = { + address: parsedEnv.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS, fromBlock: firstBlockListening, toBlock: "latest", - topics: eventDecryptionEBool, + topics: eventDecryption, }; - const pastRequestsEbool = await ethers.provider.getLogs(filterDecryptionEBool); - for (const request of pastRequestsEbool) { - const event = ifaceEventDecryptionEBool.parseLog(request); + const pastRequests = await ethers.provider.getLogs(filterDecryption); + for (const request of pastRequests) { + const event = ifaceEventDecryption.parseLog(request); const requestID = event.args[0]; - const cts = event.args[1]; + const handles = event.args[1]; + const typesList = handles.map((handle) => parseInt(handle.toString(16).slice(-4, -2), 16)); const msgValue = event.args[4]; + const passSignaturesToCaller = event.args[6]; if (!results.includes(requestID)) { // if request is not already fulfilled if (mocked) { // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestBool( - requestID, - cts.map((value) => value === 1n), - { value: msgValue }, + await awaitCoprocessor(); + + // first check tat all handles are allowed for decryption + const aclFactory = await ethers.getContractFactory("fhevmTemp/contracts/ACL.sol:ACL"); + const acl = aclFactory.attach(aclAdd); + const isAllowedForDec = await Promise.all(handles.map(async (handle) => acl.isAllowedForDecryption(handle))); + if (!allTrue(isAllowedForDec)) { + throw new Error("Some handle is not authorized for decryption"); + } + const types = typesList.map((num) => CiphertextType[num]); + const values = await Promise.all(handles.map(async (handle) => BigInt(await getClearText(handle)))); + const valuesFormatted = values.map((value, index) => + types[index] === "address" ? "0x" + value.toString(16).padStart(40, "0") : value, + ); + const valuesFormatted2 = valuesFormatted.map((value, index) => + typesList[index] === 9 ? "0x" + value.toString(16).padStart(128, "0") : value, + ); + const valuesFormatted3 = valuesFormatted2.map((value, index) => + typesList[index] === 10 ? "0x" + value.toString(16).padStart(256, "0") : value, + ); + const valuesFormatted4 = valuesFormatted3.map((value, index) => + typesList[index] === 11 ? "0x" + value.toString(16).padStart(512, "0") : value, ); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } - const eventDecryptionEUint4 = await oracle.filters.EventDecryptionEUint4().getTopicFilter(); - const filterDecryptionEUint4 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEUint4, - }; - const pastRequestsEUint4 = await ethers.provider.getLogs(filterDecryptionEUint4); - for (const request of pastRequestsEUint4) { - const event = ifaceEventDecryptionEUint4.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestUint4(requestID, [...cts], { value: msgValue }); + const abiCoder = new ethers.AbiCoder(); + let encodedData; + let calldata; + if (!passSignaturesToCaller) { + encodedData = abiCoder.encode(["uint256", ...types], [31, ...valuesFormatted4]); // 31 is just a dummy uint256 requestID to get correct abi encoding for the remaining arguments (i.e everything except the requestID) + calldata = "0x" + encodedData.slice(66); // we just pop the dummy requestID to get the correct value to pass for `decryptedCts` + } else { + encodedData = abiCoder.encode(["uint256", ...types, "bytes[]"], [31, ...valuesFormatted4, []]); // adding also a dummy empty array of bytes for correct abi-encoding when used with signatures + calldata = "0x" + encodedData.slice(66).slice(0, -64); // we also pop the last 32 bytes (empty bytes[]) + } + + const numSigners = +process.env.NUM_KMS_SIGNERS!; + const decryptResultsEIP712signatures = await computeDecryptSignatures(handles, calldata, numSigners); + const tx = await gateway + .connect(relayer) + .fulfillRequest(requestID, calldata, decryptResultsEIP712signatures, { value: msgValue }); await tx.wait(); } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx + // in fhEVM mode we must wait until the gateway service relayer submits the decryption fulfillment tx await waitNBlocks(1); await fulfillAllPastRequestsIds(mocked); } } } +}; - const eventDecryptionEUint8 = await oracle.filters.EventDecryptionEUint8().getTopicFilter(); - const filterDecryptionEUint8 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEUint8, - }; - const pastRequestsEUint8 = await ethers.provider.getLogs(filterDecryptionEUint8); - for (const request of pastRequestsEUint8) { - const event = ifaceEventDecryptionEUint8.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestUint8(requestID, [...cts], { value: msgValue }); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } +async function computeDecryptSignatures( + handlesList: bigint[], + decryptedResult: string, + numSigners: number, +): Promise { + const signatures: string[] = []; + + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = process.env[`PRIVATE_KEY_KMS_SIGNER_${idx}`]; + if (privKeySigner) { + const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); + const signature = await kmsSign(handlesList, decryptedResult, kmsSigner); + signatures.push(signature); + } else { + throw new Error(`Private key for signer ${idx} not found in environment variables`); } } - - const eventDecryptionEUint16 = await oracle.filters.EventDecryptionEUint16().getTopicFilter(); - const filterDecryptionEUint16 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEUint16, + return signatures; +} + +async function kmsSign(handlesList: bigint[], decryptedResult: string, kmsSigner: Wallet) { + const kmsAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.kmsverifier"), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + const chainId = (await ethers.provider.getNetwork()).chainId; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsAdd, }; - const pastRequestsEUint16 = await ethers.provider.getLogs(filterDecryptionEUint16); - for (const request of pastRequestsEUint16) { - const event = ifaceEventDecryptionEUint16.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestUint16(requestID, [...cts], { value: msgValue }); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } - const eventDecryptionEUint32 = await oracle.filters.EventDecryptionEUint32().getTopicFilter(); - const filterDecryptionEUint32 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEUint32, + const types = { + DecryptionResult: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "decryptedResult", + type: "bytes", + }, + ], }; - const pastRequestsEUint32 = await ethers.provider.getLogs(filterDecryptionEUint32); - for (const request of pastRequestsEUint32) { - const event = ifaceEventDecryptionEUint32.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestUint32(requestID, [...cts], { value: msgValue }); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } - - const eventDecryptionEUint64 = await oracle.filters.EventDecryptionEUint64().getTopicFilter(); - const filterDecryptionEUint64 = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEUint64, + const message = { + aclAddress: aclAdd, + handlesList: handlesList, + decryptedResult: decryptedResult, }; - const pastRequestsEUint64 = await ethers.provider.getLogs(filterDecryptionEUint64); - for (const request of pastRequestsEUint64) { - const event = ifaceEventDecryptionEUint64.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestUint64(requestID, [...cts], { value: msgValue }); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } - const eventDecryptionEAddress = await oracle.filters.EventDecryptionEAddress().getTopicFilter(); - const filterDecryptionEAddress = { - address: process.env.ORACLE_CONTRACT_PREDEPLOY_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionEAddress, - }; - const pastRequestsEAddress = await ethers.provider.getLogs(filterDecryptionEAddress); - for (const request of pastRequestsEAddress) { - const event = ifaceEventDecryptionEAddress.parseLog(request); - const requestID = event.args[0]; - const cts = event.args[1]; - const msgValue = event.args[4]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - const tx = await oracle.connect(relayer).fulfillRequestAddress(requestID, [...cts], { value: msgValue }); - await tx.wait(); - } else { - // in fhEVM mode we must wait until the oracle service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } -}; + const signature = await kmsSigner.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} diff --git a/test/coprocessorUtils.ts b/test/coprocessorUtils.ts new file mode 100644 index 0000000..d082313 --- /dev/null +++ b/test/coprocessorUtils.ts @@ -0,0 +1,903 @@ +import dotenv from "dotenv"; +import { log2 } from "extra-bigint"; +import * as fs from "fs"; +import { ethers } from "hardhat"; +import hre from "hardhat"; +import { Database } from "sqlite3"; + +import operatorsPrices from "./operatorsPrices.json"; + +const parsedEnvCoprocessor = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.exec")); +const coprocAddress = parsedEnvCoprocessor.TFHE_EXECUTOR_CONTRACT_ADDRESS; + +let firstBlockListening = 0; +let lastBlockSnapshot = 0; +let lastCounterRand = 0; +let counterRand = 0; + +//const db = new Database('./sql.db'); // on-disk db for debugging +const db = new Database(":memory:"); + +export function insertSQL(handle: string, clearText: BigInt, replace: boolean = false) { + if (replace) { + // this is useful if using snapshots while sampling different random numbers on each revert + db.run("INSERT OR REPLACE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } else { + db.run("INSERT OR IGNORE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } +} + +// Decrypt any handle, bypassing ACL +// WARNING : only for testing or internal use +export const getClearText = async (handle: BigInt): Promise => { + const handleStr = "0x" + handle.toString(16).padStart(64, "0"); + + return new Promise((resolve, reject) => { + let attempts = 0; + const maxRetries = 100; + + function executeQuery() { + db.get("SELECT clearText FROM ciphertexts WHERE handle = ?", [handleStr], (err, row) => { + if (err) { + reject(new Error(`Error querying database: ${err.message}`)); + } else if (row) { + resolve(row.clearText); + } else if (attempts < maxRetries) { + attempts++; + executeQuery(); + } else { + reject(new Error("No record found after maximum retries")); + } + }); + } + + executeQuery(); + }); +}; + +db.serialize(() => db.run("CREATE TABLE IF NOT EXISTS ciphertexts (handle BINARY PRIMARY KEY,clearText TEXT)")); + +interface FHEVMEvent { + eventName: string; + args: object; +} + +const NumBits = { + 0: 1n, //ebool + 1: 4n, //euint4 + 2: 8n, //euint8 + 3: 16n, //euint16 + 4: 32n, //euint32 + 5: 64n, //euint64 + 6: 128n, //euint128 + 7: 160n, //eaddress + 8: 256n, //euint256 + 9: 512n, //ebytes64 + 10: 1024n, //ebytes128 + 11: 2048n, //ebytes256 +}; + +export function numberToEvenHexString(num: number) { + if (typeof num !== "number" || num < 0) { + throw new Error("Input should be a non-negative number."); + } + let hexString = num.toString(16); + if (hexString.length % 2 !== 0) { + hexString = "0" + hexString; + } + return hexString; +} + +function getRandomBigInt(numBits: number): bigint { + if (numBits <= 0) { + throw new Error("Number of bits must be greater than 0"); + } + const numBytes = Math.ceil(numBits / 8); + const randomBytes = new Uint8Array(numBytes); + crypto.getRandomValues(randomBytes); + let randomBigInt = BigInt(0); + for (let i = 0; i < numBytes; i++) { + randomBigInt = (randomBigInt << BigInt(8)) | BigInt(randomBytes[i]); + } + const mask = (BigInt(1) << BigInt(numBits)) - BigInt(1); + randomBigInt = randomBigInt & mask; + return randomBigInt; +} + +function bitwiseNotUintBits(value: BigInt, numBits: number) { + if (typeof value !== "bigint") { + throw new TypeError("The input value must be a BigInt."); + } + if (typeof numBits !== "number" || numBits <= 0) { + throw new TypeError("The numBits parameter must be a positive integer."); + } + // Create the mask with numBits bits set to 1 + const BIT_MASK = (BigInt(1) << BigInt(numBits)) - BigInt(1); + return ~value & BIT_MASK; +} + +export const awaitCoprocessor = async (): Promise => { + await processAllPastTFHEExecutorEvents(); +}; + +const abi = [ + "event FheAdd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheSub(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMul(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheDiv(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRem(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitAnd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitOr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitXor(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEq(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEqBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheNe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheGe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheGt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMin(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMax(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeg(uint256 ct, uint256 result)", + "event FheNot(uint256 ct, uint256 result)", + "event VerifyCiphertext(bytes32 inputHandle,address userAddress,bytes inputProof,bytes1 inputType,uint256 result)", + "event Cast(uint256 ct, bytes1 toType, uint256 result)", + "event TrivialEncrypt(uint256 pt, bytes1 toType, uint256 result)", + "event TrivialEncryptBytes(bytes pt, bytes1 toType, uint256 result)", + "event FheIfThenElse(uint256 control, uint256 ifTrue, uint256 ifFalse, uint256 result)", + "event FheRand(bytes1 randType, uint256 result)", + "event FheRandBounded(uint256 upperBound, bytes1 randType, uint256 result)", +]; + +async function processAllPastTFHEExecutorEvents() { + const provider = ethers.provider; + const latestBlockNumber = await provider.getBlockNumber(); + + if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + [lastBlockSnapshot, lastCounterRand] = await provider.send("get_lastBlockSnapshot"); + if (lastBlockSnapshot < firstBlockListening) { + firstBlockListening = lastBlockSnapshot + 1; + counterRand = Number(lastCounterRand); + } + } + + const contract = new ethers.Contract(coprocAddress, abi, provider); + + // Fetch all events emitted by the contract + const filter = { + address: coprocAddress, + fromBlock: firstBlockListening, + toBlock: latestBlockNumber, + }; + + const logs = await provider.getLogs(filter); + + const events = logs + .map((log) => { + try { + const parsedLog = contract.interface.parseLog(log); + return { + eventName: parsedLog.name, + args: parsedLog.args, + }; + } catch (e) { + // If the log cannot be parsed, skip it + return null; + } + }) + .filter((event) => event !== null); + + firstBlockListening = latestBlockNumber + 1; + if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await provider.send("set_lastBlockSnapshot", [firstBlockListening]); + } + events.map(async (event) => await insertHandleFromEvent(event)); +} + +async function insertHandleFromEvent(event: FHEVMEvent) { + let handle; + let clearText; + let clearLHS; + let clearRHS; + let resultType; + let shift; + + switch (event.eventName) { + case "TrivialEncrypt": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "TrivialEncryptBytes": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "FheAdd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) + event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) + BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(ethers.toBeHex(handle, 32), clearText); + break; + + case "FheSub": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) - event.args[1]; + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) - BigInt(clearRHS); + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheMul": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) * event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) * BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheDiv": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) / event.args[1]; + } else { + throw new Error("Non-scalar div not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheRem": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) % event.args[1]; + } else { + throw new Error("Non-scalar rem not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheBitAnd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) & event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) & BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitOr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) | event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) | BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitXor": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) ^ event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) ^ BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) << event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) << BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >> event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >> BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheEq": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheEqBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNeBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) <= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) <= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheMax": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "FheMin": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "Cast": + resultType = parseInt(event.args[1]); + handle = ethers.toBeHex(event.args[2], 32); + clearText = BigInt(await getClearText(event.args[0])) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "FheNot": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + insertSQL(handle, clearText); + break; + + case "FheNeg": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + clearText = (clearText + 1n) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "VerifyCiphertext": + handle = event.args[0]; + try { + await getClearText(BigInt(handle)); + } catch { + throw Error("User input was not found in DB"); + } + break; + + case "FheIfThenElse": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + handle = ethers.toBeHex(event.args[3], 32); + const clearControl = BigInt(await getClearText(event.args[0])); + const clearIfTrue = BigInt(await getClearText(event.args[1])); + const clearIfFalse = BigInt(await getClearText(event.args[2])); + if (clearControl === 1n) { + clearText = clearIfTrue; + } else { + clearText = clearIfFalse; + } + insertSQL(handle, clearText); + break; + + case "FheRand": + resultType = parseInt(event.args[0], 16); + handle = ethers.toBeHex(event.args[1], 32); + clearText = getRandomBigInt(Number(NumBits[resultType])); + insertSQL(handle, clearText, true); + counterRand++; + break; + + case "FheRandBounded": + resultType = parseInt(event.args[1], 16); + handle = ethers.toBeHex(event.args[2], 32); + clearText = getRandomBigInt(Number(log2(BigInt(event.args[0])))); + insertSQL(handle, clearText, true); + counterRand++; + break; + } +} + +export function getFHEGasFromTxReceipt(receipt: ethers.TransactionReceipt): number { + if (hre.network.name !== "hardhat") { + throw Error("FHEGas tracking is currently implemented only in mocked mode"); + } + if (receipt.status === 0) { + throw new Error("Transaction reverted"); + } + const contract = new ethers.Contract(coprocAddress, abi, ethers.provider); + const relevantLogs = receipt.logs.filter((log: ethers.Log) => { + if (log.address.toLowerCase() !== coprocAddress.toLowerCase()) { + return false; + } + try { + const parsedLog = contract.interface.parseLog({ + topics: log.topics, + data: log.data, + }); + return abi.some((item) => item.startsWith(`event ${parsedLog.name}`) && parsedLog.name !== "VerifyCiphertext"); + } catch { + return false; + } + }); + const FHELogs = relevantLogs.map((log: ethers.Log) => { + const parsedLog = contract.interface.parseLog({ + topics: log.topics, + data: log.data, + }); + return { + name: parsedLog.name, + args: parsedLog.args, + }; + }); + let FHEGasConsumed = 0; + for (const event of FHELogs) { + let type; + let handle; + switch (event.name) { + case "TrivialEncrypt": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorsPrices["trivialEncrypt"].types[type]; + break; + + case "TrivialEncryptBytes": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorsPrices["trivialEncrypt"].types[type]; + break; + + case "FheAdd": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheAdd"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheAdd"].nonScalar[type]; + } + break; + + case "FheSub": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheSub"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheSub"].nonScalar[type]; + } + break; + + case "FheMul": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheMul"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheMul"].nonScalar[type]; + } + break; + + case "FheDiv": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheDiv"].scalar[type]; + } else { + throw new Error("Non-scalar div not implemented yet"); + } + break; + + case "FheRem": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheRem"].scalar[type]; + } else { + throw new Error("Non-scalar rem not implemented yet"); + } + break; + + case "FheBitAnd": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheBitAnd"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheBitAnd"].nonScalar[type]; + } + break; + + case "FheBitOr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheBitOr"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheBitOr"].nonScalar[type]; + } + break; + + case "FheBitXor": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheBitXor"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheBitXor"].nonScalar[type]; + } + break; + + case "FheShl": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheBitShl"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheBitShl"].nonScalar[type]; + } + break; + + case "FheShr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheBitShr"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheBitShr"].nonScalar[type]; + } + break; + + case "FheRotl": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheRotl"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheRotl"].nonScalar[type]; + } + break; + + case "FheRotr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheRotr"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheRotr"].nonScalar[type]; + } + break; + + case "FheEq": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheEq"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheEq"].nonScalar[type]; + } + break; + + case "FheEqBytes": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheEq"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheEq"].nonScalar[type]; + } + + case "FheNe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheNe"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheNe"].nonScalar[type]; + } + break; + + case "FheNeBytes": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheNe"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheNe"].nonScalar[type]; + } + break; + + case "FheGe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheGe"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheGe"].nonScalar[type]; + } + break; + + case "FheGt": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheGt"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheGt"].nonScalar[type]; + } + break; + + case "FheLe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheLe"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheLe"].nonScalar[type]; + } + break; + + case "FheLt": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheLt"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheLt"].nonScalar[type]; + } + break; + + case "FheMax": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheMax"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheMax"].nonScalar[type]; + } + break; + + case "FheMin": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorsPrices["fheMin"].scalar[type]; + } else { + FHEGasConsumed += operatorsPrices["fheMin"].nonScalar[type]; + } + break; + + case "Cast": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorsPrices["cast"].types[type]; + break; + + case "FheNot": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorsPrices["fheNot"].types[type]; + break; + + case "FheNeg": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorsPrices["fheNeg"].types[type]; + break; + + case "FheIfThenElse": + handle = ethers.toBeHex(event.args[3], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorsPrices["ifThenElse"].types[type]; + break; + + case "FheRand": + type = parseInt(event.args[0], 16); + FHEGasConsumed += operatorsPrices["fheRand"].types[type]; + break; + + case "FheRandBounded": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorsPrices["fheRandBounded"].types[type]; + break; + } + } + return FHEGasConsumed; +} diff --git a/test/dao/Comp.fixture.ts b/test/dao/Comp.fixture.ts deleted file mode 100644 index 8be962d..0000000 --- a/test/dao/Comp.fixture.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ethers } from "hardhat"; - -import type { Comp } from "../../types"; -import { getSigners } from "../signers"; - -export async function deployCompFixture(): Promise { - const signers = await getSigners(); - - const contractFactory = await ethers.getContractFactory("Comp"); - const contract = await contractFactory.connect(signers.alice).deploy(signers.alice.address); - await contract.waitForDeployment(); - - return contract; -} diff --git a/test/dao/Comp.ts b/test/dao/Comp.ts deleted file mode 100644 index 1f6800d..0000000 --- a/test/dao/Comp.ts +++ /dev/null @@ -1,327 +0,0 @@ -import { expect } from "chai"; -import { ethers, network } from "hardhat"; - -import { createInstances } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { createTransaction, mineNBlocks, waitNBlocks } from "../utils"; -import { deployCompFixture } from "./Comp.fixture"; -import { delegateBySigSignature } from "./DelegateBySig"; - -describe("Comp", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const contract = await deployCompFixture(); - this.contractAddress = await contract.getAddress(); - this.comp = contract; - this.instances = await createInstances(this.contractAddress, ethers, this.signers); - }); - - // 9000n , 31337n - - it("only owner could set allowed contract", async function () { - const tx = await this.comp.setAllowedContract("0xE359a77c3bFE58792FB167D05720e37032A1e520"); - await tx.wait(); - - if (network.name === "hardhat") { - // mocked mode - await expect(this.comp.connect(this.signers.bob).setAllowedContract("0x9d3e06a2952dc49EDCc73e41C76645797fC53967")) - .to.be.revertedWithCustomError(this.comp, "OwnableUnauthorizedAccount") - .withArgs(this.signers.bob.address); - } else { - // fhevm-mode - const tx = await this.comp - .connect(this.signers.bob) - .setAllowedContract("0x9d3e06a2952dc49EDCc73e41C76645797fC53967", { gasLimit: 1_000_000 }); - await expect(tx.wait()).to.throw; - } - }); - - it("only allowed contract can call getPriorVotes", async function () { - await expect(this.comp.getPriorVotes("0xE359a77c3bFE58792FB167D05720e37032A1e520", 0)).to.be.revertedWith( - "Caller not allowed to call this function", - ); - }); - - it("should transfer tokens", async function () { - const encryptedAmountToTransfer = this.instances.alice.encrypt64(2_000_000n * 10n ** 6n); - const transferTransac = await this.comp["transfer(address,bytes)"]( - this.signers.bob.address, - encryptedAmountToTransfer, - ); - - await transferTransac.wait(); - - const aliceToken = this.instances.alice.getPublicKey(this.contractAddress); - const encryptedAliceBalance = await this.comp.balanceOf( - this.signers.alice.address, - aliceToken.publicKey, - aliceToken.signature, - ); - // Decrypt Alice's balance - const aliceBalance = this.instances.alice.decrypt(this.contractAddress, encryptedAliceBalance); - expect(aliceBalance).to.equal(8_000_000n * 10n ** 6n); - - let encryptedAliceVotes = await this.comp.getMyCurrentVotes(aliceToken.publicKey, aliceToken.signature); - // Decrypt Alice's current votes - let aliceCurrentVotes = this.instances.alice.decrypt(this.contractAddress, encryptedAliceVotes); - expect(aliceCurrentVotes).to.equal(0n); - - // Bob should not be able to decrypt Alice's votes - await expect( - this.comp.connect(this.signers.bob).getMyCurrentVotes(aliceToken.publicKey, aliceToken.signature), - ).to.be.revertedWith("EIP712 signer and transaction signer do not match"); - - const tx = await this.comp.delegate(this.signers.alice); - await tx.wait(); - encryptedAliceVotes = await this.comp.getMyCurrentVotes(aliceToken.publicKey, aliceToken.signature); - // Decrypt Alice's current votes - aliceCurrentVotes = this.instances.alice.decrypt(this.contractAddress, encryptedAliceVotes); - expect(aliceCurrentVotes).to.equal(8_000_000n * 10n ** 6n); - - const tx2 = await createTransaction(this.comp.delegate, this.signers.bob); - await tx2.wait(); - encryptedAliceVotes = await this.comp.getMyCurrentVotes(aliceToken.publicKey, aliceToken.signature); - // Decrypt Alice's current votes - aliceCurrentVotes = this.instances.alice.decrypt(this.contractAddress, encryptedAliceVotes); - expect(aliceCurrentVotes).to.equal(0n); - - const bobToken = this.instances.bob.getPublicKey(this.contractAddress); - const encryptedBobBalance = await this.comp - .connect(this.signers.bob) - .balanceOf(this.signers.bob.address, bobToken.publicKey, bobToken.signature); - // Decrypt Bob's balance - const bobBalance = this.instances.bob.decrypt(this.contractAddress, encryptedBobBalance); - expect(bobBalance).to.equal(2_000_000n * 10n ** 6n); - }); - - it("can't transfer to nor from null address", async function () { - const nullAddress = "0x0000000000000000000000000000000000000000"; - const encryptedAmountToTransfer = this.instances.alice.encrypt64(1n * 10n ** 6n); - const encryptedAmountToTransferNull = this.instances.alice.encrypt64(0n); - if (network.name === "hardhat") { - // mocked mode - await expect(this.comp["transfer(address,bytes)"](nullAddress, encryptedAmountToTransfer)).to.be.revertedWith( - "Comp::_transferTokens: cannot transfer to the zero address", - ); - await expect( - this.comp["transferFrom(address,address,bytes)"]( - nullAddress, - this.signers.bob.address, - encryptedAmountToTransfer, - ), - ).to.be.revertedWith("Comp::_transferTokens: cannot transfer from the zero address"); - } else { - // fhevm-mode - const tx = await this.comp["transfer(address,bytes)"](nullAddress, encryptedAmountToTransferNull, { - gasLimit: 1_000_000, - }); - - await expect(tx.wait()).to.throw; - const tx2 = await this.comp["transferFrom(address,address,bytes)"]( - nullAddress, - this.signers.bob.address, - encryptedAmountToTransferNull, - { gasLimit: 1_000_000 }, - ); - await expect(tx2.wait()).to.throw; - } - }); - - it("can't transfer from null address", async function () { - const tx = await this.comp.setAllowedContract("0xE359a77c3bFE58792FB167D05720e37032A1e520"); - await tx.wait(); - - if (network.name === "hardhat") { - // mocked mode - await expect(this.comp.connect(this.signers.bob).setAllowedContract("0x9d3e06a2952dc49EDCc73e41C76645797fC53967")) - .to.be.revertedWithCustomError(this.comp, "OwnableUnauthorizedAccount") - .withArgs(this.signers.bob.address); - } else { - // fhevm-mode - const tx = await this.comp - .connect(this.signers.bob) - .setAllowedContract("0x9d3e06a2952dc49EDCc73e41C76645797fC53967", { gasLimit: 1_000_000 }); - await expect(tx.wait()).to.throw; - } - }); - - it("can delegate votes via delegateBySig if signature is valid", async function () { - const delegatee = this.signers.bob.address; - const nonce = 0; - const latestBlockNumber = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(latestBlockNumber); - const expiry = block!.timestamp + 100; - const [v, r, s] = await delegateBySigSignature(this.signers.alice, delegatee, this.comp, nonce, expiry); - - const tx = await this.comp.delegateBySig(delegatee, nonce, expiry, v, r, s); - await tx.wait(); - - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress); - const encryptedCurrentVotes = await this.comp - .connect(this.signers.bob) - .getMyCurrentVotes(tokenBob.publicKey, tokenBob.signature); - const currentVotes = this.instances.bob.decrypt(this.contractAddress, encryptedCurrentVotes); - expect(currentVotes).to.equal(10_000_000n * 10n ** 6n); - - if (network.name === "hardhat") { - // can't reuse same nonce when delegating by sig - await expect(this.comp.delegateBySig(delegatee, nonce, expiry, v, r, s)).to.be.revertedWith( - "Comp::delegateBySig: invalid nonce", - ); - - // can't use invalid signature when delegating by sig - await expect(this.comp.delegateBySig(delegatee, nonce, expiry, 30, r, s)).to.be.revertedWith( - "Comp::delegateBySig: invalid signature", - ); - - // can't use signature after expiry - ethers.provider.send("evm_increaseTime", ["0xffff"]); - const [v2, r2, s2] = await delegateBySigSignature(this.signers.alice, delegatee, this.comp, 1, expiry); - await expect(this.comp.delegateBySig(delegatee, nonce, expiry, v2, r2, s2)).to.be.revertedWith( - "Comp::delegateBySig: signature expired", - ); - } - }); - - it("comp becomes obsolete after max(uint32) blocks", async function () { - if (network.name === "hardhat") { - // mocked mode - const tx = await this.comp.delegate(this.signers.bob.address); - await tx.wait(); - const idSnapshot = await ethers.provider.send("evm_snapshot"); - - await mineNBlocks(2 ** 32); - const encryptedAmountToTransfer = this.instances.alice.encrypt64(2_000_000n * 10n ** 6n); - await expect( - this.comp["transfer(address,bytes)"](this.signers.carol.address, encryptedAmountToTransfer), - ).to.be.revertedWith("Comp::_writeCheckpoint: block number exceeds 32 bits"); - await ethers.provider.send("evm_revert", [idSnapshot]); - } - }); - - it("user can request his past votes via getMyPriorVotes", async function () { - const aliceToken = this.instances.alice.getPublicKey(this.contractAddress); - const initBlock = await ethers.provider.getBlockNumber(); - let aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - initBlock - 1, - aliceToken.publicKey, - aliceToken.signature, - ); - let aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(0n); - - const tx = await this.comp.delegate(this.signers.alice.address); - await tx.wait(); - const firstCheckPointBlockNumber = await ethers.provider.getBlockNumber(); - await waitNBlocks(1); - - aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - firstCheckPointBlockNumber, - aliceToken.publicKey, - aliceToken.signature, - ); - aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(10000000000000n); - - aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - firstCheckPointBlockNumber - 1, - aliceToken.publicKey, - aliceToken.signature, - ); - aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(0n); - - await expect( - this.comp.getMyPriorVotes(firstCheckPointBlockNumber + 1, aliceToken.publicKey, aliceToken.signature), - ).to.be.revertedWith("Comp::getPriorVotes: not yet determined"); - - // Bob cannot decrypt Alice's prior votes - await expect( - this.comp - .connect(this.signers.bob) - .getMyPriorVotes(firstCheckPointBlockNumber - 1, aliceToken.publicKey, aliceToken.signature), - ).to.be.revertedWith("EIP712 signer and transaction signer do not match"); - - const encryptedAmountToTransfer = this.instances.alice.encrypt64(2_000_000n * 10n ** 6n); - const transferTransac = await this.comp["transfer(address,bytes)"]( - this.signers.bob.address, - encryptedAmountToTransfer, - ); - await transferTransac.wait(); - const secondCheckPointBlockNumber = await ethers.provider.getBlockNumber(); - await waitNBlocks(1); - - aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - firstCheckPointBlockNumber, - aliceToken.publicKey, - aliceToken.signature, - ); - aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(10000000000000n); - - const encryptedAmountToTransfer2 = this.instances.alice.encrypt64(2_000_000n * 10n ** 6n); - const transferTransac2 = await this.comp["transfer(address,bytes)"]( - this.signers.carol.address, - encryptedAmountToTransfer2, - ); - await transferTransac2.wait(); - await ethers.provider.getBlockNumber(); // third CheckPoint - await waitNBlocks(1); - - aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - secondCheckPointBlockNumber, - aliceToken.publicKey, - aliceToken.signature, - ); - aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(8000000000000n); - - aliceMyPriorVotesEnc = await this.comp.getMyPriorVotes( - secondCheckPointBlockNumber + 1, - aliceToken.publicKey, - aliceToken.signature, - ); - aliceMyPriorVotes = this.instances.alice.decrypt(this.contractAddress, aliceMyPriorVotesEnc); - expect(aliceMyPriorVotes).to.be.equal(8000000000000n); - }); - - it("different voters can delegate to same delegatee", async function () { - const encryptedAmountToTransfer = this.instances.alice.encrypt64(2_000_000n * 10n ** 6n); - const tx1 = await this.comp["transfer(address,bytes)"](this.signers.bob.address, encryptedAmountToTransfer); - await tx1.wait(); - - const tx2 = await this.comp.delegate(this.signers.carol); - await tx2.wait(); - - const tx3 = await createTransaction(this.comp.connect(this.signers.bob).delegate, this.signers.carol); - await tx3.wait(); - - const carolToken = this.instances.carol.getPublicKey(this.contractAddress); - let encryptedCarolVotes = await this.comp - .connect(this.signers.carol) - .getMyCurrentVotes(carolToken.publicKey, carolToken.signature); - // Decrypt Alice's current votes - let carolCurrentVotes = this.instances.carol.decrypt(this.contractAddress, encryptedCarolVotes); - expect(carolCurrentVotes).to.equal(10000000000000n); - }); - - it("number of checkpoints is incremented once per block, even when written multiple times in same block", async function () { - if (network.name === "hardhat") { - // mocked mode - await network.provider.send("evm_setAutomine", [false]); - await network.provider.send("evm_setIntervalMining", [0]); - // do two checkpoints in same block - await this.comp.delegate(this.signers.bob); - await this.comp.delegate(this.signers.carol); - await network.provider.send("evm_mine"); - await network.provider.send("evm_setAutomine", [true]); - expect(await this.comp.numCheckpoints(this.signers.alice)).to.be.equal(0n); - expect(await this.comp.numCheckpoints(this.signers.bob)).to.be.equal(1n); - expect(await this.comp.numCheckpoints(this.signers.carol)).to.be.equal(1n); - } - }); -}); diff --git a/test/dao/GovernorZama.fixture.ts b/test/dao/GovernorZama.fixture.ts deleted file mode 100644 index c0f8e06..0000000 --- a/test/dao/GovernorZama.fixture.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ethers } from "hardhat"; - -import { Comp } from "../../types"; -import type { GovernorZama, Timelock } from "../../types"; -import { getSigners } from "../signers"; - -export async function deployTimelockFixture(admin: string): Promise { - const signers = await getSigners(); - - const timelockFactory = await ethers.getContractFactory("Timelock"); - const timelock = await timelockFactory.connect(signers.alice).deploy(admin, 60 * 60 * 24 * 2); - - await timelock.waitForDeployment(); - - return timelock; -} - -export async function deployGovernorZamaFixture(compContract: Comp, timelock: Timelock): Promise { - const signers = await getSigners(); - const votingPeriod = 5; // WARNING: We use 5 only for testing purpose, DO NOT use this value in production, typically it should be at least a few days, default was 3 days originally i.e votingPeriod=21600 blocks if 12s per block - const governorFactory = await ethers.getContractFactory("GovernorZama"); - const governor = await governorFactory - .connect(signers.alice) - .deploy(timelock.getAddress(), compContract.getAddress(), signers.alice.address, votingPeriod); - await governor.waitForDeployment(); - - return governor; -} diff --git a/test/dao/GovernorZama.ts b/test/dao/GovernorZama.ts deleted file mode 100644 index b1fec9d..0000000 --- a/test/dao/GovernorZama.ts +++ /dev/null @@ -1,521 +0,0 @@ -import { expect } from "chai"; -import { ethers, network } from "hardhat"; - -import { createInstances } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { createTransaction, waitNBlocks } from "../utils"; -import { deployCompFixture } from "./Comp.fixture"; -import { deployGovernorZamaFixture, deployTimelockFixture } from "./GovernorZama.fixture"; - -describe("GovernorZama", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - this.comp = await deployCompFixture(); - const instancesComp = await createInstances(await this.comp.getAddress(), ethers, this.signers); - const encryptedAmountToTransfer = instancesComp.alice.encrypt64(500_000n * 10n ** 6n); - const transfer1 = await this.comp["transfer(address,bytes)"](this.signers.bob.address, encryptedAmountToTransfer); - await transfer1.wait(); - const transfer2 = await this.comp["transfer(address,bytes)"](this.signers.carol.address, encryptedAmountToTransfer); - await transfer2.wait(); - - const delegate1 = await this.comp.delegate(this.signers.alice); - const delegate2 = await this.comp.connect(this.signers.bob).delegate(this.signers.bob); - const delegate3 = await this.comp.connect(this.signers.carol).delegate(this.signers.carol); - await Promise.all([delegate1, delegate2, delegate3]); - await waitNBlocks(1); - - const precomputedGovernorAddress = ethers.getCreateAddress({ - from: this.signers.alice.address, - nonce: (await this.signers.alice.getNonce()) + 1, - }); - - this.timelock = await deployTimelockFixture(precomputedGovernorAddress); - - const governor = await deployGovernorZamaFixture(this.comp, this.timelock); - this.contractAddress = await governor.getAddress(); - - this.governor = governor; - this.instances = await createInstances(this.contractAddress, ethers, this.signers); - - const transaction = await this.comp.setAllowedContract(this.contractAddress); - await transaction.wait(); - }); - - it("could not deploy timelock contract if delay is below 2 days or above 31 days", async function () { - const timelockFactory = await ethers.getContractFactory("Timelock"); - - if (network.name === "hardhat") { - await expect( - timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 1), - ).to.be.revertedWith("Timelock::constructor: Delay must exceed minimum delay."); // 1 day < 2 days - await expect( - timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 31), - ).to.be.revertedWith("Timelock::setDelay: Delay must not exceed maximum delay."); // 31 days > 30 days - } else { - // fhevm-mode - await expect(timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 1)).to - .throw; - await expect(timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 31)).to - .throw; - } - }); - - it("should propose a vote", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - const txproposal = await tx.wait(); - expect(txproposal?.status).to.equal(1); - const proposalId = await this.governor.latestProposalIds(this.signers.alice.address); - const proposals = await this.governor.getProposalInfo(proposalId); - expect(proposals.id).to.equal(proposalId); - expect(proposals.proposer).to.equal(this.signers.alice.address); - - const actions = await this.governor.getActions(1); - expect(actions[0][0]).to.equal(this.signers.alice.address); - expect(actions[1][0]).to.equal(0); - expect(actions[2][0]).to.equal("getBalanceOf(address)"); - expect(actions[3][0]).to.equal(callDatas[0]); - }); - - it("should vote and return a Succeed", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - const txproposal = await tx.wait(); - expect(txproposal?.status).to.equal(1); - - const proposalId = await this.governor.latestProposalIds(this.signers.alice.address); - - await waitNBlocks(2); - // Cast some votes - const encryptedSupportBob = this.instances.bob.encryptBool(true); - const txVoteBob = await createTransaction( - this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], - proposalId, - encryptedSupportBob, - ); - // bob can get his receipt - - const encryptedSupportCarol = this.instances.carol.encryptBool(true); - const txVoteCarol = await createTransaction( - this.governor.connect(this.signers.carol)["castVote(uint256,bytes)"], - proposalId, - encryptedSupportCarol, - ); - - const [bobResults, carolResults] = await Promise.all([txVoteBob.wait(), txVoteCarol.wait()]); - expect(bobResults?.status).to.equal(1); - expect(carolResults?.status).to.equal(1); - - await waitNBlocks(4); - - const state = await this.governor.state(proposalId); - expect(state).to.equal(4n); - }); - - it("should vote and return a Defeated ", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - const proposal = await tx.wait(); - expect(proposal?.status).to.equal(1); - const proposalId = await this.governor.latestProposalIds(this.signers.alice.address); - await waitNBlocks(2); - - // Cast some votes - const encryptedSupportBob = this.instances.bob.encryptBool(false); - const txVoteBob = await createTransaction( - this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], - proposalId, - encryptedSupportBob, - ); - - const encryptedSupportCarol = this.instances.carol.encryptBool(true); - const txVoteCarol = await createTransaction( - this.governor.connect(this.signers.carol)["castVote(uint256,bytes)"], - proposalId, - encryptedSupportCarol, - ); - - const [bobResults, aliceResults] = await Promise.all([txVoteBob.wait(), txVoteCarol.wait()]); - expect(bobResults?.status).to.equal(1); - expect(aliceResults?.status).to.equal(1); - await waitNBlocks(4); - - const state = await this.governor.state(proposalId); - expect(state).to.equal(3n); - - // cannot queue defeated proposal - await expect(this.governor.queue(1)).to.throw; - }); - - it("should cancel", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - const proposal = await tx.wait(); - expect(proposal?.status).to.equal(1); - const proposalId = await this.governor.latestProposalIds(this.signers.alice.address); - await waitNBlocks(2); - - const state = await this.governor.state(proposalId); - expect(state).to.equal(1n); - - await expect(this.governor.connect(this.signers.dave).cancel(proposalId)).to.throw; // non-guardian or non-proposer is unable to cancel - - const txCancel = await this.governor.cancel(proposalId); - await txCancel.wait(); - const newState = await this.governor.state(proposalId); - expect(newState).to.equal(2n); - }); - - it("only guardian could queue setTimelockPendingAdmin then execute it, and then acceptAdmin", async function () { - const latestBlockNumber = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(latestBlockNumber); - const expiry = block!.timestamp + 60 * 60 * 24 * 2 + 60; - - const tx = await this.governor.__queueSetTimelockPendingAdmin(this.signers.bob, expiry); - await tx.wait(); - if (network.name === "hardhat") { - // hardhat cheatcodes are available only in mocked mode - await expect(this.governor.__executeSetTimelockPendingAdmin(this.signers.bob, expiry)).to.be.revertedWith( - "Timelock::executeTransaction: Transaction hasn't surpassed time lock.", - ); - await expect( - this.governor.connect(this.signers.carol).__queueSetTimelockPendingAdmin(this.signers.bob, expiry), - ).to.be.revertedWith("GovernorAlpha::__queueSetTimelockPendingAdmin: sender must be gov guardian"); - - await ethers.provider.send("evm_increaseTime", ["0x2a33c"]); - await expect( - this.governor.connect(this.signers.carol).__executeSetTimelockPendingAdmin(this.signers.bob, expiry), - ).to.be.revertedWith("GovernorAlpha::__executeSetTimelockPendingAdmin: sender must be gov guardian"); - const tx3 = await this.governor.__executeSetTimelockPendingAdmin(this.signers.bob, expiry); - await tx3.wait(); - - await expect(this.timelock.acceptAdmin()).to.be.revertedWith( - "Timelock::acceptAdmin: Call must come from pendingAdmin.", - ); - const tx4 = await this.timelock.connect(this.signers.bob).acceptAdmin(); - await tx4.wait(); - - const latestBlockNumber = await ethers.provider.getBlockNumber(); - const block = await ethers.provider.getBlock(latestBlockNumber); - const expiry2 = block!.timestamp + 60 * 60 * 24 * 2 + 60; - const timeLockAdd = await this.timelock.getAddress(); - const callData = ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.contractAddress]); - const tx5 = await this.timelock - .connect(this.signers.bob) - .queueTransaction(timeLockAdd, 0, "setPendingAdmin(address)", callData, expiry2); - await tx5.wait(); - await ethers.provider.send("evm_increaseTime", ["0x2a33c"]); - const tx6 = await this.timelock - .connect(this.signers.bob) - .executeTransaction(timeLockAdd, 0, "setPendingAdmin(address)", callData, expiry2); - await tx6.wait(); - await expect(this.governor.connect(this.signers.bob).__acceptAdmin()).to.be.revertedWith( - "GovernorAlpha::__acceptAdmin: sender must be gov guardian", - ); - const tx7 = await this.governor.__acceptAdmin(); - await tx7.wait(); - expect(await this.timelock.admin()).to.eq(this.contractAddress); - } - }); - - it("only guardian can call __abdicate", async function () { - await expect(this.governor.connect(this.signers.bob).__abdicate()).to.throw; - const tx = await this.governor.__abdicate(); - await tx.wait(); - }); - - it("user can't propose if his votes are below the minimal threshold", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - if (network.name === "hardhat") { - await expect( - createTransaction( - this.governor.connect(this.signers.dave).propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ), - ).to.be.revertedWith("GovernorAlpha::propose: proposer votes below proposal threshold"); - } else { - await expect( - createTransaction( - this.governor.connect(this.signers.dave).propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ), - ).to.throw; - } - }); - - it("all arrays of a proposal should be of same length, non null and less than max operations", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - await expect( - createTransaction( - this.governor.propose, - [this.signers.alice, this.signers.bob], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ), - ).to.throw; - - await expect(createTransaction(this.governor.propose, [], [], [], [], "do nothing")).to.throw; - - await expect( - createTransaction( - this.governor.propose, - new Array(11).fill(this.signers.alice), - new Array(11).fill("0"), - new Array(11).fill("getBalanceOf(address)"), - new Array(11).fill(callDatas[0]), - "do nothing", - ), - ).to.throw; - }); - - it("proposer cannot make a new proposal while he still has an already pending or active proposal", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - await tx.wait(); - - await expect( - createTransaction( - this.governor.propose, - [this.signers.bob], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ), - ).to.throw; - - await waitNBlocks(1); - - await expect( - createTransaction( - this.governor.propose, - [this.signers.bob], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ), - ).to.throw; - - const tx2 = await createTransaction(this.governor.connect(this.signers.bob).cancel, 1); - await tx2.wait(); - - await waitNBlocks(1); - - const tx3 = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - await tx3.wait(); - - expect(await this.governor.latestProposalIds(this.signers.alice)).to.equal(2); - - await expect(this.governor.state(0)).to.be.revertedWith("GovernorAlpha::state: invalid proposal id"); - await expect(this.governor.state(10)).to.be.revertedWith("GovernorAlpha::state: invalid proposal id"); - expect(await this.governor.state(1)).to.equal(2); - expect(await this.governor.state(2)).to.equal(0); - }); - - it("can propose, then vote once, then queue, then execute", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - - await tx.wait(); - - await waitNBlocks(2); - const encryptedSupportBob = this.instances.bob.encryptBool(true); - const txVoteBob = await createTransaction( - this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], - 1, - encryptedSupportBob, - ); - await txVoteBob.wait(); - - await expect( - createTransaction(this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], 1, encryptedSupportBob), - ).to.throw; // cannot vote twice - - await waitNBlocks(5); - - const encryptedSupportAlice = this.instances.alice.encryptBool(true); - await expect( - createTransaction(this.governor.connect(this.signers.alice)["castVote(uint256,bytes)"], 1, encryptedSupportAlice), - ).to.throw; // voting is closed after voting period - - if (network.name === "hardhat") { - const txQueue = await this.governor.queue(1); - await txQueue.wait(); - await ethers.provider.send("evm_increaseTime", ["0x2a33c"]); - const txExecute = await this.governor.execute(1); - await txExecute.wait(); - - // cannot cancel executed proposal - await expect(this.governor.cancel(1)).to.be.revertedWith( - "GovernorAlpha::cancel: cannot cancel executed proposal", - ); - - await expect(this.governor.getProposalInfo(2)).to.be.revertedWith("Invalid proposalId"); - } - }); - - it("cannot queue two identical transactions at same eta", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - - if (network.name === "hardhat") { - // mocked mode - const tx1 = await this.governor.propose( - [this.signers.alice, this.signers.alice], - ["0", "0"], - ["getBalanceOf(address)", "getBalanceOf(address)"], - new Array(2).fill(callDatas[0]), - "do nothing", - { - gasLimit: 500_000, - }, - ); - await tx1.wait(); - - await waitNBlocks(1); - const encryptedSupportBob = this.instances.bob.encryptBool(true); - const txVoteBob = await createTransaction( - this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], - 1, - encryptedSupportBob, - ); - await txVoteBob.wait(); - - await waitNBlocks(5); - - await expect(this.governor.queue(1)).to.be.revertedWith( - "GovernorAlpha::_queueOrRevert: proposal action already queued at eta", - ); - await expect(this.governor.execute(1)).to.be.revertedWith( - "GovernorAlpha::execute: proposal can only be executed if it is queued", - ); // cannot execute non-queued proposal - } - }); - - it("proposal expires after grace period", async function () { - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - - await tx.wait(); - - await waitNBlocks(2); - const encryptedSupportBob = this.instances.bob.encryptBool(true); - const txVoteBob = await createTransaction( - this.governor.connect(this.signers.bob)["castVote(uint256,bytes)"], - 1, - encryptedSupportBob, - ); - await txVoteBob.wait(); - - if (network.name === "hardhat") { - await waitNBlocks(5); - const txQueue = await this.governor.queue(1); - await txQueue.wait(); - await ethers.provider.send("evm_increaseTime", ["0xffffff"]); - await waitNBlocks(1); - await expect(this.governor.execute(1)).to.be.revertedWith( - "GovernorAlpha::execute: proposal can only be executed if it is queued", - ); - expect(await this.governor.state(1)).to.equal(6); - } - }); - - it("voter can get his receipt via reencryption", async function () { - const aliceToken = this.instances.alice.getPublicKey(this.contractAddress); - const callDatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.alice.address])]; - const tx = await createTransaction( - this.governor.propose, - [this.signers.alice], - ["0"], - ["getBalanceOf(address)"], - callDatas, - "do nothing", - ); - await tx.wait(); - - await waitNBlocks(2); - // Cast some votes - const encryptedSupportAlice = this.instances.alice.encryptBool(true); - const tx2 = await createTransaction(this.governor["castVote(uint256,bytes)"], 1, encryptedSupportAlice); - await tx2.wait(); - - const encryptedAliceVotes = await this.governor.getMyReceipt(1, aliceToken.publicKey, aliceToken.signature); - // Decrypt Alice's balance - const aliceVotes = this.instances.alice.decrypt(this.contractAddress, encryptedAliceVotes[2]); - expect(aliceVotes).to.equal(9_000_000n * 10n ** 6n); - - await expect( - this.governor.connect(this.signers.bob).getMyReceipt(1, aliceToken.publicKey, aliceToken.signature), - ).to.be.revertedWith("EIP712 signer and transaction signer do not match"); - }); -}); diff --git a/test/encryptedERC20/EncryptedERC20.fixture.ts b/test/encryptedERC20/EncryptedERC20.fixture.ts index 87d8051..8e0782e 100644 --- a/test/encryptedERC20/EncryptedERC20.fixture.ts +++ b/test/encryptedERC20/EncryptedERC20.fixture.ts @@ -1,14 +1,45 @@ import { ethers } from "hardhat"; -import type { EncryptedERC20Mintable } from "../../types"; -import { getSigners } from "../signers"; +import type { IEncryptedERC20, TestEncryptedERC20Mintable } from "../../types"; +import { reencryptEuint64 } from "../reencrypt"; +import { Signers } from "../signers"; +import { FhevmInstances } from "../types"; -export async function deployEncryptedERC20Fixture(): Promise { - const signers = await getSigners(); - - const contractFactory = await ethers.getContractFactory("EncryptedERC20Mintable"); - const contract = await contractFactory.connect(signers.alice).deploy("Naraggara", "NARA", signers.alice.address); // City of Zama's battle +export async function deployEncryptedERC20Fixture( + signers: Signers, + name: string, + symbol: string, + owner: string, +): Promise { + const contractFactory = await ethers.getContractFactory("TestEncryptedERC20Mintable"); + const contract = await contractFactory + .connect(signers[owner as keyof Signers]) + .deploy(name, symbol, signers[owner as keyof Signers].address); await contract.waitForDeployment(); - return contract; } + +export async function reencryptAllowance( + signers: Signers, + instances: FhevmInstances, + account: string, + spender: string, + token: IEncryptedERC20, + tokenAddress: string, +): Promise { + const allowanceHandle = await token.allowance(signers[account as keyof Signers], signers[spender as keyof Signers]); + const allowance = await reencryptEuint64(signers, instances, account, allowanceHandle, tokenAddress); + return allowance; +} + +export async function reencryptBalance( + signers: Signers, + instances: FhevmInstances, + account: string, + token: IEncryptedERC20, + tokenAddress: string, +): Promise { + const balanceHandle = await token.balanceOf(signers[account as keyof Signers]); + const balance = await reencryptEuint64(signers, instances, account, balanceHandle, tokenAddress); + return balance; +} diff --git a/test/encryptedERC20/EncryptedERC20.test.ts b/test/encryptedERC20/EncryptedERC20.test.ts new file mode 100644 index 0000000..89fd400 --- /dev/null +++ b/test/encryptedERC20/EncryptedERC20.test.ts @@ -0,0 +1,398 @@ +import { expect } from "chai"; + +import { createInstances } from "../instance"; +import { getSigners, initSigners } from "../signers"; +import { deployEncryptedERC20Fixture, reencryptAllowance, reencryptBalance } from "./EncryptedERC20.fixture"; + +describe("EncryptedERC20", function () { + before(async function () { + await initSigners(2); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const contract = await deployEncryptedERC20Fixture(this.signers, "Naraggara", "NARA", "alice"); + this.encryptedERC20Address = await contract.getAddress(); + this.encryptedERC20 = contract; + this.instances = await createInstances(this.signers); + }); + + it("post-deployment state", async function () { + expect(await this.encryptedERC20.totalSupply()).to.equal(0); + expect(await this.encryptedERC20.name()).to.equal("Naraggara"); + expect(await this.encryptedERC20.symbol()).to.equal("NARA"); + expect(await this.encryptedERC20.decimals()).to.be.eq(BigInt(6)); + }); + + it("should mint the contract", async function () { + const mintAmount = 1000; + const tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); + + expect(await this.encryptedERC20.totalSupply()).to.equal(mintAmount); + }); + + it("should transfer tokens between two users", async function () { + const mintAmount = 10_000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount - transferAmount); + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(transferAmount); + }); + + it("should not transfer tokens between two users if transfer amount is higher than balance", async function () { + // @dev There is no transfer done since the mint amount is smaller than the transfer + // amount. + const mintAmount = 1000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(0); + }); + + it("should be able to transferFrom only if allowance is sufficient", async function () { + // @dev There is no transfer done since the mint amount is smaller than the transfer + // amount. + const mintAmount = 10_000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const inputAlice = this.instances.alice.createEncryptedInput( + this.encryptedERC20Address, + this.signers.alice.address, + ); + inputAlice.add64(transferAmount); + const encryptedAllowanceAmount = await inputAlice.encrypt(); + + tx = await this.encryptedERC20["approve(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + await tx.wait(); + + // @dev The allowance amount is set to be equal to the transfer amount. + expect( + await reencryptAllowance( + this.signers, + this.instances, + "alice", + "bob", + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal(transferAmount); + + const bobErc20 = this.encryptedERC20.connect(this.signers.bob); + const inputBob1 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address); + inputBob1.add64(transferAmount + 1); // above allowance so next tx should actually not send any token + const encryptedTransferAmount = await inputBob1.encrypt(); + + const tx2 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx2.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); // check that transfer did not happen, as expected + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(0); // check that transfer did not happen, as expected + + const inputBob2 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address); + inputBob2.add64(transferAmount); // below allowance so next tx should send token + const encryptedTransferAmount2 = await inputBob2.encrypt(); + + const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.bob.address, + encryptedTransferAmount2.handles[0], + encryptedTransferAmount2.inputProof, + ); + await tx3.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount - transferAmount); // check that transfer did happen this time + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(transferAmount); // check that transfer did happen this time + + // Verify Alice's allowance is 0 + expect( + await reencryptAllowance( + this.signers, + this.instances, + "alice", + "bob", + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal(0); + }); + + it("should not be able to read the allowance if not spender/owner after initialization", async function () { + const amount = 10_000; + + const inputAlice = this.instances.alice.createEncryptedInput( + this.encryptedERC20Address, + this.signers.alice.address, + ); + inputAlice.add64(amount); + const encryptedAllowanceAmount = await inputAlice.encrypt(); + + const tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + await tx.wait(); + + const allowanceHandleAlice = await this.encryptedERC20.allowance(this.signers.alice, this.signers.bob); + + const { publicKey: publicKeyCarol, privateKey: privateKeyCarol } = this.instances.carol.generateKeypair(); + const eip712Carol = this.instances.carol.createEIP712(publicKeyCarol, this.encryptedERC20Address); + const signatureCarol = await this.signers.carol.signTypedData( + eip712Carol.domain, + { Reencrypt: eip712Carol.types.Reencrypt }, + eip712Carol.message, + ); + + try { + await this.instances.bob.reencrypt( + allowanceHandleAlice, + privateKeyCarol, + publicKeyCarol, + signatureCarol.replace("0x", ""), + this.encryptedERC20Address, + this.signers.carol.address, + ); + + expect.fail("Expected an error to be thrown - Carol should not be able to reencrypt Bob's allowance for Alice"); + } catch (error) { + if (error instanceof Error) { + expect(error.message).to.equal("User is not authorized to reencrypt this handle!"); + } + } + }); + + it("should not be able to read the balance if not user after initialization", async function () { + // Mint is used to initialize the balanceOf(alice) + const amount = 10_000; + const tx = await this.encryptedERC20.connect(this.signers.alice).mint(amount); + await tx.wait(); + + const balanceHandleAlice = await this.encryptedERC20.balanceOf(this.signers.alice); + + const { publicKey: publicKeyBob, privateKey: privateKeyBob } = this.instances.bob.generateKeypair(); + const eip712Bob = this.instances.bob.createEIP712(publicKeyBob, this.encryptedERC20Address); + const signatureBob = await this.signers.bob.signTypedData( + eip712Bob.domain, + { Reencrypt: eip712Bob.types.Reencrypt }, + eip712Bob.message, + ); + + try { + await this.instances.bob.reencrypt( + balanceHandleAlice, + privateKeyBob, + publicKeyBob, + signatureBob.replace("0x", ""), + this.encryptedERC20Address, + this.signers.bob.address, + ); + expect.fail("Expected an error to be thrown - Bob should not be able to reencrypt Alice's balance"); + } catch (error) { + if (error instanceof Error) { + expect(error.message).to.equal("User is not authorized to reencrypt this handle!"); + } + } + }); + + it("receiver cannot be null address", async function () { + const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + const mintAmount = 100_000; + const transferAmount = 50_000; + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + await expect( + this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + NULL_ADDRESS, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ), + ).to.be.revertedWithCustomError(this.encryptedERC20, "ReceiverAddressNull"); + }); + + it("sender who is not allowed cannot transfer using a handle from another account", async function () { + const mintAmount = 100_000; + const transferAmount = 50_000; + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + const balanceHandleAlice = await this.encryptedERC20.balanceOf(this.signers.alice.address); + + await expect( + this.encryptedERC20.connect(this.signers.bob).transfer(this.signers.carol.address, balanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("sender who is not allowed cannot transferFrom using a handle from another account", async function () { + const mintAmount = 100_000; + const transferAmount = 50_000; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + let input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(mintAmount); + const encryptedAllowanceAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + input = this.instances.carol.createEncryptedInput(this.encryptedERC20Address, this.signers.carol.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.carol) + ["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.carol.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + const allowanceHandleAlice = await this.encryptedERC20.allowance( + this.signers.alice.address, + this.signers.carol.address, + ); + + await expect( + this.encryptedERC20 + .connect(this.signers.bob) + .transferFrom(this.signers.alice.address, this.signers.bob.address, allowanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("sender who is not allowed cannot approve using a handle from another account", async function () { + const amount = 100_000; + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(amount); + const encryptedAllowanceAmount = await input.encrypt(); + + const tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + await tx.wait(); + + const allowanceHandleAlice = await this.encryptedERC20.allowance( + this.signers.alice.address, + this.signers.carol.address, + ); + + await expect( + this.encryptedERC20.connect(this.signers.bob).approve(this.signers.carol.address, allowanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("EncryptedERC20Mintable - only owner can mint", async function () { + await expect(this.encryptedERC20.connect(this.signers.bob).mint(1)).to.be.revertedWithCustomError( + this.encryptedERC20, + "OwnableUnauthorizedAccount", + ); + }); +}); diff --git a/test/encryptedERC20/EncryptedERC20.ts b/test/encryptedERC20/EncryptedERC20.ts deleted file mode 100644 index bd144a2..0000000 --- a/test/encryptedERC20/EncryptedERC20.ts +++ /dev/null @@ -1,374 +0,0 @@ -import { expect } from "chai"; -import { ethers, network } from "hardhat"; - -import { createInstances } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { deployEncryptedERC20Fixture } from "./EncryptedERC20.fixture"; - -describe("EncryptedERC20", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const contract = await deployEncryptedERC20Fixture(); - this.contractAddress = await contract.getAddress(); - this.erc20 = contract; - this.instances = await createInstances(this.contractAddress, ethers, this.signers); - }); - - it("should read token name and symbol", async function () { - const name = await this.erc20.name(); - expect(name, "Naraggara"); - const symbol = await this.erc20.symbol(); - expect(symbol, "NARA"); - }); - - it("should mint the contract", async function () { - const transaction = await this.erc20.mint(1000, this.signers.alice.address); - await transaction.wait(); - // Call the method - const token = this.instances.alice.getPublicKey(this.contractAddress) || { - signature: "", - publicKey: "", - }; - const encryptedBalance = await this.erc20.balanceOf(this.signers.alice, token.publicKey, token.signature); - // Decrypt the balance - const balance = this.instances.alice.decrypt(this.contractAddress, encryptedBalance); - expect(balance).to.equal(1000); - - const totalSupply = await this.erc20.totalSupply(); - // Decrypt the total supply - expect(totalSupply).to.equal(1000); - }); - - it("non-owner should be unable to mint", async function () { - if (network.name === "hardhat") { - // mocked mode - await expect(this.erc20.connect(this.signers.bob).mint(1000, this.signers.alice.address)) - .to.be.revertedWithCustomError(this.erc20, "OwnableUnauthorizedAccount") - .withArgs(this.signers.bob.address); - } else { - // fhevm-mode - const tx = await this.erc20 - .connect(this.signers.bob) - .mint(1000, this.signers.alice.address, { gasLimit: 1_000_000n }); - await expect(tx.wait()).to.throw; - } - }); - - it("should transfer tokens between two users", async function () { - const transaction = await this.erc20.mint(10000, this.signers.alice.address); - await transaction.wait(); - - const encryptedTransferAmount = this.instances.alice.encrypt64(1337); - const tx = await this.erc20["transfer(address,bytes)"](this.signers.bob.address, encryptedTransferAmount); - await tx.wait(); - - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - - const encryptedBalanceAlice = await this.erc20.balanceOf( - this.signers.alice, - tokenAlice.publicKey, - tokenAlice.signature, - ); - - // Decrypt the balance - const balanceAlice = this.instances.alice.decrypt(this.contractAddress, encryptedBalanceAlice); - - expect(balanceAlice).to.equal(10000 - 1337); - - const bobErc20 = this.erc20.connect(this.signers.bob); - - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - - const encryptedBalanceBob = await bobErc20.balanceOf(this.signers.bob, tokenBob.publicKey, tokenBob.signature); - - // Decrypt the balance - const balanceBob = this.instances.bob.decrypt(this.contractAddress, encryptedBalanceBob); - - expect(balanceBob).to.equal(1337); - }); - - it("should only be able to read hiw own balance", async function () { - const transaction = await this.erc20.mint(10000, this.signers.alice.address); - await transaction.wait(); - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - const encryptedBalanceAlice = await this.erc20.balanceOf( - this.signers.alice, - tokenAlice.publicKey, - tokenAlice.signature, - ); - // Decrypt own balance - const balanceAlice = this.instances.alice.decrypt(this.contractAddress, encryptedBalanceAlice); - expect(balanceAlice).to.equal(10000); - - // Alice cannot decrypt Bob's balance - await expect(this.erc20.balanceOf(this.signers.bob, tokenAlice.publicKey, tokenAlice.signature)).to.be.revertedWith( - "User cannot reencrypt a non-owned wallet balance", - ); - - // Alice cannot read her own balance with an invalid EIP-712 signature - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - await expect(this.erc20.balanceOf(this.signers.alice, tokenBob.publicKey, tokenBob.signature)).to.be.revertedWith( - "EIP712 signer and transaction signer do not match", - ); - }); - - it("balanceOfMe should recover own's balance handle", async function () { - expect(await this.erc20.balanceOfMe()).to.be.eq(0n); // Alice's initial handle is 0 - const transaction = await this.erc20.mint(1000, this.signers.alice.address); - await transaction.wait(); - if (network.name === "hardhat") { - // mocked mode - expect(await this.erc20.balanceOfMe()).to.be.eq(1000n); - } else { - // fhevm node mode (real handle) - expect(await this.erc20.balanceOfMe()).to.be.gt(0); - } - }); - - it("should not transfer tokens between two users", async function () { - const transaction = await this.erc20.mint(1000, this.signers.alice.address); - await transaction.wait(); - - const encryptedTransferAmount = this.instances.alice.encrypt64(1337); - const tx = await this.erc20["transfer(address,bytes)"](this.signers.bob.address, encryptedTransferAmount); - await tx.wait(); - - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - - const encryptedBalanceAlice = await this.erc20.balanceOf( - this.signers.alice, - tokenAlice.publicKey, - tokenAlice.signature, - ); - - // Decrypt the balance - const balanceAlice = this.instances.alice.decrypt(this.contractAddress, encryptedBalanceAlice); - - expect(balanceAlice).to.equal(1000); - - const bobErc20 = this.erc20.connect(this.signers.bob); - - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - - const encryptedBalanceBob = await bobErc20.balanceOf(this.signers.bob, tokenBob.publicKey, tokenBob.signature); - - // Decrypt the balance - const balanceBob = this.instances.bob.decrypt(this.contractAddress, encryptedBalanceBob); - - expect(balanceBob).to.equal(0); - }); - - it("should be able to transferFrom only if allowance is sufficient", async function () { - const transaction = await this.erc20.mint(10000, this.signers.alice.address); - await transaction.wait(); - - const encryptedAllowanceAmount = this.instances.alice.encrypt64(1337); - const tx = await this.erc20["approve(address,bytes)"](this.signers.bob.address, encryptedAllowanceAmount); - await tx.wait(); - - const bobErc20 = this.erc20.connect(this.signers.bob); - const encryptedTransferAmount = this.instances.bob.encrypt64(1338); // above allowance so next tx should actually not send any token - const tx2 = await bobErc20["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount, - ); - await tx2.wait(); - - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - const encryptedBalanceAlice = await this.erc20.balanceOf( - this.signers.alice, - tokenAlice.publicKey, - tokenAlice.signature, - ); - - // Decrypt the balance - const balanceAlice = this.instances.alice.decrypt(this.contractAddress, encryptedBalanceAlice); - expect(balanceAlice).to.equal(10000); // check that transfer did not happen, as expected - - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - const encryptedBalanceBob = await bobErc20.balanceOf(this.signers.bob, tokenBob.publicKey, tokenBob.signature); - // Decrypt the balance - const balanceBob = this.instances.bob.decrypt(this.contractAddress, encryptedBalanceBob); - expect(balanceBob).to.equal(0); // check that transfer did not happen, as expected - - const encryptedTransferAmount2 = this.instances.bob.encrypt64(1337); // below allowance so next tx should send token - const tx3 = await bobErc20["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount2, - ); - await tx3.wait(); - - const encryptedBalanceAlice2 = await this.erc20.balanceOf( - this.signers.alice, - tokenAlice.publicKey, - tokenAlice.signature, - ); - // Decrypt the balance - const balanceAlice2 = this.instances.alice.decrypt(this.contractAddress, encryptedBalanceAlice2); - expect(balanceAlice2).to.equal(10000 - 1337); // check that transfer did happen this time - - const encryptedBalanceBob2 = await bobErc20.balanceOf(this.signers.bob, tokenBob.publicKey, tokenBob.signature); - const balanceBob2 = this.instances.bob.decrypt(this.contractAddress, encryptedBalanceBob2); - expect(balanceBob2).to.equal(1337); // check that transfer did happen this time - }); - - it("only spender and owner could read their allowance", async function () { - const transaction = await this.erc20.mint(10000, this.signers.alice.address); - await transaction.wait(); - - const encryptedAllowanceAmount = this.instances.alice.encrypt64(1337); - const tx = await this.erc20["approve(address,bytes)"](this.signers.bob.address, encryptedAllowanceAmount); - await tx.wait(); - - const bobErc20 = this.erc20.connect(this.signers.bob); - const encryptedTransferAmount = this.instances.bob.encrypt64(337); - const tx2 = await bobErc20["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount, - ); - await tx2.wait(); - - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - - // Alice decrypts the allowance for (Alice,Bob) - let encryptedAllowanceAliceBob = await this.erc20.allowance( - this.signers.alice, - this.signers.bob, - tokenAlice.publicKey, - tokenAlice.signature, - ); - let allowanceAliceBob = this.instances.alice.decrypt(this.contractAddress, encryptedAllowanceAliceBob); - expect(allowanceAliceBob).to.equal(1000); - - // Bob decrypts the allowance for (Alice,Bob) - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - encryptedAllowanceAliceBob = await bobErc20.allowance( - this.signers.alice, - this.signers.bob, - tokenBob.publicKey, - tokenBob.signature, - ); - allowanceAliceBob = this.instances.bob.decrypt(this.contractAddress, encryptedAllowanceAliceBob); - expect(allowanceAliceBob).to.equal(1000); - - // Carol cannot get the allowance for (Alice,Bob) - const tokenCarol = this.instances.carol.getPublicKey(this.contractAddress)!; - await expect( - this.erc20 - .connect(this.signers.carol) - .allowance(this.signers.alice, this.signers.bob, tokenCarol.publicKey, tokenCarol.signature), - ).to.be.revertedWith("Caller must be owner or spender"); - - // Alice cannot decrypt with invalid EIP-712 signature - await expect( - this.erc20.allowance(this.signers.alice, this.signers.bob, tokenBob.publicKey, tokenBob.signature), - ).to.be.revertedWith("EIP712 signer and transaction signer do not match"); - - // Carol would get a null allowance for (Alice,Carol) - expect( - this.instances.carol.decrypt( - this.contractAddress, - await this.erc20 - .connect(this.signers.carol) - .allowance(this.signers.alice, this.signers.carol, tokenCarol.publicKey, tokenCarol.signature), - ), - ).to.equal(0n); - }); - - it("should handle errors correctly", async function () { - // case 1 succesful transfer - const transaction = await this.erc20.mint(10000, this.signers.alice.address); - await transaction.wait(); - let encryptedTransferAmount = this.instances.alice.encrypt64(1337); - const tx = await this.erc20["transfer(address,bytes)"](this.signers.bob.address, encryptedTransferAmount); - await tx.wait(); - const tokenAlice = this.instances.alice.getPublicKey(this.contractAddress)!; - let encryptedErrorCode = await this.erc20.reencryptError(0n, tokenAlice.publicKey, tokenAlice.signature); - // Decrypt the error code - let errorCode = this.instances.alice.decrypt(this.contractAddress, encryptedErrorCode); - expect(errorCode).to.equal(0); - - // case 2 failed transfer - encryptedTransferAmount = this.instances.alice.encrypt64(100000n); - const tx2 = await this.erc20["transfer(address,bytes)"](this.signers.bob.address, encryptedTransferAmount); - await tx2.wait(); - encryptedErrorCode = await this.erc20.reencryptError(1n, tokenAlice.publicKey, tokenAlice.signature); - // Decrypt the error code - errorCode = this.instances.alice.decrypt(this.contractAddress, encryptedErrorCode); - expect(errorCode).to.equal(1); - - // case 3 successful transferFrom - const encryptedAllowanceAmount = this.instances.alice.encrypt64(20000); - const tx3 = await this.erc20["approve(address,bytes)"](this.signers.bob.address, encryptedAllowanceAmount); - await tx3.wait(); - - const bobErc20 = this.erc20.connect(this.signers.bob); - encryptedTransferAmount = this.instances.bob.encrypt64(1338); - const tx4 = await bobErc20["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount, - ); - await tx4.wait(); - const tokenBob = this.instances.bob.getPublicKey(this.contractAddress)!; - encryptedErrorCode = await bobErc20.reencryptError(2n, tokenBob.publicKey, tokenBob.signature); - // Decrypt the error code - errorCode = this.instances.bob.decrypt(this.contractAddress, encryptedErrorCode); - expect(errorCode).to.equal(0); - // Bob cannot decrypt with invalid EIP-712 signature - await expect(bobErc20.reencryptError(2n, tokenAlice.publicKey, tokenAlice.signature)).to.be.revertedWith( - "EIP712 signer and transaction signer do not match", - ); - - // case 4 failed transferFrom because of unsufficient balance - encryptedTransferAmount = this.instances.bob.encrypt64(15000); - const tx5 = await bobErc20["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount, - ); - await tx5.wait(); - encryptedErrorCode = await bobErc20.reencryptError(3n, tokenBob.publicKey, tokenBob.signature); - // Decrypt the error code - errorCode = this.instances.bob.decrypt(this.contractAddress, encryptedErrorCode); - expect(errorCode).to.equal(1); - - // case 5 failed transferFrom because of unsufficient allowance - const tokenCarol = this.instances.carol.getPublicKey(this.contractAddress)!; - encryptedTransferAmount = this.instances.bob.encrypt64(1); - const tx6 = await this.erc20 - .connect(this.signers.carol) - ["transferFrom(address,address,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount, - ); - await tx6.wait(); - encryptedErrorCode = await this.erc20 - .connect(this.signers.carol) - .reencryptError(4n, tokenCarol.publicKey, tokenCarol.signature); - // Decrypt the error code - errorCode = this.instances.carol.decrypt(this.contractAddress, encryptedErrorCode); - expect(errorCode).to.equal(2); - - // Cannot decrypt an invalid transferID - if (network.name !== "hardhat") { - // only true in real fhEVM mode (TFHE.isInitialized always returns true in mocked mode) - await expect( - this.erc20.connect(this.signers.carol).reencryptError(5n, tokenCarol.publicKey, tokenCarol.signature), - ).to.be.revertedWith("Invalid transferId"); - } - - // Non-sender cannot decrypt - await expect( - this.erc20.connect(this.signers.alice).reencryptError(4n, tokenAlice.publicKey, tokenAlice.signature), - ).to.be.revertedWith("Only spender can reencrypt his error"); - }); -}); diff --git a/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts b/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts new file mode 100644 index 0000000..d438d7e --- /dev/null +++ b/test/encryptedERC20/EncryptedERC20WithErrors.fixture.ts @@ -0,0 +1,46 @@ +import { ethers } from "hardhat"; + +import type { TestEncryptedERC20WithErrorsMintable } from "../../types"; +import { reencryptEuint8 } from "../reencrypt"; +import { Signers } from "../signers"; +import { FhevmInstances } from "../types"; + +export async function deployEncryptedERC20WithErrorsFixture( + signers: Signers, + name: string, + symbol: string, + owner: string, +): Promise { + const contractFactory = await ethers.getContractFactory("TestEncryptedERC20WithErrorsMintable"); + const contract = await contractFactory + .connect(signers[owner as keyof Signers]) + .deploy(name, symbol, signers[owner as keyof Signers].address); + await contract.waitForDeployment(); + return contract; +} + +export async function checkErrorCode( + signers: Signers, + instances: FhevmInstances, + account: string, + transferId: bigint, + token: TestEncryptedERC20WithErrorsMintable, + tokenAddress: string, +): Promise { + const errorCodeHandle = await token.getErrorCodeForTransferId(transferId); + const errorCode = await reencryptEuint8(signers, instances, account, errorCodeHandle, tokenAddress); + switch (errorCode) { + case BigInt(0): { + return "NO_ERROR"; + } + case BigInt(1): { + return "UNSUFFICIENT_BALANCE"; + } + case BigInt(2): { + return "UNSUFFICIENT_APPROVAL"; + } + default: { + throw "Error code is invalid"; + } + } +} diff --git a/test/encryptedERC20/EncryptedERC20WithErrors.test.ts b/test/encryptedERC20/EncryptedERC20WithErrors.test.ts new file mode 100644 index 0000000..f604129 --- /dev/null +++ b/test/encryptedERC20/EncryptedERC20WithErrors.test.ts @@ -0,0 +1,512 @@ +import { expect } from "chai"; + +import { createInstances } from "../instance"; +import { getSigners, initSigners } from "../signers"; +import { reencryptAllowance, reencryptBalance } from "./EncryptedERC20.fixture"; +import { checkErrorCode, deployEncryptedERC20WithErrorsFixture } from "./EncryptedERC20WithErrors.fixture"; + +describe("EncryptedERC20WithErrors", function () { + const DEFAULT_TRANSFER_ID = BigInt(0); + const DEFAULT_SECOND_TRANSFER_ID = BigInt(1); + + before(async function () { + await initSigners(2); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const contract = await deployEncryptedERC20WithErrorsFixture(this.signers, "Naraggara", "NARA", "alice"); + this.encryptedERC20Address = await contract.getAddress(); + this.encryptedERC20 = contract; + this.instances = await createInstances(this.signers); + }); + + it("post-deployment state", async function () { + expect(await this.encryptedERC20.totalSupply()).to.equal(0); + expect(await this.encryptedERC20.name()).to.equal("Naraggara"); + expect(await this.encryptedERC20.symbol()).to.equal("NARA"); + expect(await this.encryptedERC20.decimals()).to.be.eq(BigInt(6)); + expect(await this.encryptedERC20.getTotalNumberErrors()).to.be.eq(BigInt(2)); + }); + + it("should mint the contract", async function () { + const mintAmount = 1000; + const tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); + + expect(await this.encryptedERC20.totalSupply()).to.equal(mintAmount); + }); + + it("should transfer tokens between two users", async function () { + const mintAmount = 10_000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount - transferAmount); + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(transferAmount); + + // Check the error code matches no error + expect( + await checkErrorCode( + this.signers, + this.instances, + "alice", + DEFAULT_TRANSFER_ID, + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal("NO_ERROR"); + + // Check that both the from/to address can read the error code + expect( + await checkErrorCode( + this.signers, + this.instances, + "bob", + DEFAULT_TRANSFER_ID, + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal("NO_ERROR"); + }); + + it("should not transfer tokens between two users if transfer amount is higher than balance", async function () { + // @dev There is no transfer done since the mint amount is smaller than the transfer + // amount. + const mintAmount = 1000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + tx = await this.encryptedERC20["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(0); + + // Check that the error code matches if balance is not sufficient + expect( + await checkErrorCode( + this.signers, + this.instances, + "bob", + DEFAULT_TRANSFER_ID, + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal("UNSUFFICIENT_BALANCE"); + }); + + it("should be able to transferFrom only if allowance is sufficient", async function () { + // @dev There is no transfer done since the mint amount is smaller than the transfer + // amount. + const mintAmount = 10_000; + const transferAmount = 1337; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const inputAlice = this.instances.alice.createEncryptedInput( + this.encryptedERC20Address, + this.signers.alice.address, + ); + inputAlice.add64(transferAmount); + const encryptedAllowanceAmount = await inputAlice.encrypt(); + + tx = await this.encryptedERC20["approve(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + await tx.wait(); + + // @dev The allowance amount is set to be equal to the transfer amount. + expect( + await reencryptAllowance( + this.signers, + this.instances, + "alice", + "bob", + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal(transferAmount); + + const bobErc20 = this.encryptedERC20.connect(this.signers.bob); + const inputBob1 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address); + inputBob1.add64(transferAmount + 1); // above allowance so next tx should actually not send any token + const encryptedTransferAmount = await inputBob1.encrypt(); + + const tx2 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx2.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount); // check that transfer did not happen, as expected + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(0); // check that transfer did not happen, as expected + + // Check that the error code matches if balance is not sufficient + expect( + await checkErrorCode( + this.signers, + this.instances, + "bob", + DEFAULT_TRANSFER_ID, + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal("UNSUFFICIENT_BALANCE"); + + const inputBob2 = this.instances.bob.createEncryptedInput(this.encryptedERC20Address, this.signers.bob.address); + inputBob2.add64(transferAmount); // below allowance so next tx should send token + const encryptedTransferAmount2 = await inputBob2.encrypt(); + + const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.bob.address, + encryptedTransferAmount2.handles[0], + encryptedTransferAmount2.inputProof, + ); + await tx3.wait(); + + // Decrypt Alice's balance + expect( + await reencryptBalance(this.signers, this.instances, "alice", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(mintAmount - transferAmount); // check that transfer did happen this time + + // Decrypt Bob's balance + expect( + await reencryptBalance(this.signers, this.instances, "bob", this.encryptedERC20, this.encryptedERC20Address), + ).to.equal(transferAmount); // check that transfer did happen this time + + // Verify Alice's allowance is 0 + expect( + await reencryptAllowance( + this.signers, + this.instances, + "alice", + "bob", + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal(0); + + // Check that the error code matches if allowance is not sufficient + expect( + await checkErrorCode( + this.signers, + this.instances, + "bob", + DEFAULT_SECOND_TRANSFER_ID, + this.encryptedERC20, + this.encryptedERC20Address, + ), + ).to.equal("UNSUFFICIENT_APPROVAL"); + }); + + it("should not be able to read the allowance if not spender/owner after initialization", async function () { + const amount = 10_000; + + const inputAlice = this.instances.alice.createEncryptedInput( + this.encryptedERC20Address, + this.signers.alice.address, + ); + inputAlice.add64(amount); + const encryptedAllowanceAmount = await inputAlice.encrypt(); + + const tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + await tx.wait(); + + const allowanceHandleAlice = await this.encryptedERC20.allowance(this.signers.alice, this.signers.bob); + + const { publicKey: publicKeyCarol, privateKey: privateKeyCarol } = this.instances.carol.generateKeypair(); + const eip712Carol = this.instances.carol.createEIP712(publicKeyCarol, this.encryptedERC20Address); + const signatureCarol = await this.signers.carol.signTypedData( + eip712Carol.domain, + { Reencrypt: eip712Carol.types.Reencrypt }, + eip712Carol.message, + ); + + try { + await this.instances.bob.reencrypt( + allowanceHandleAlice, + privateKeyCarol, + publicKeyCarol, + signatureCarol.replace("0x", ""), + this.encryptedERC20Address, + this.signers.carol.address, + ); + + expect.fail("Expected an error to be thrown - Carol should not be able to reencrypt Bob's allowance for Alice"); + } catch (error) { + if (error instanceof Error) { + expect(error.message).to.equal("User is not authorized to reencrypt this handle!"); + } + } + }); + + it("should not be able to read the balance if not user after initialization", async function () { + // Mint is used to initialize the balanceOf(alice) + const amount = 10_000; + const tx = await this.encryptedERC20.connect(this.signers.alice).mint(amount); + await tx.wait(); + + const balanceHandleAlice = await this.encryptedERC20.balanceOf(this.signers.alice); + + const { publicKey: publicKeyBob, privateKey: privateKeyBob } = this.instances.bob.generateKeypair(); + const eip712Bob = this.instances.bob.createEIP712(publicKeyBob, this.encryptedERC20Address); + const signatureBob = await this.signers.bob.signTypedData( + eip712Bob.domain, + { Reencrypt: eip712Bob.types.Reencrypt }, + eip712Bob.message, + ); + + try { + await this.instances.bob.reencrypt( + balanceHandleAlice, + privateKeyBob, + publicKeyBob, + signatureBob.replace("0x", ""), + this.encryptedERC20Address, + this.signers.bob.address, + ); + expect.fail("Expected an error to be thrown - Bob should not be able to reencrypt Alice's balance"); + } catch (error) { + if (error instanceof Error) { + expect(error.message).to.equal("User is not authorized to reencrypt this handle!"); + } + } + }); + + it("receiver cannot be null address", async function () { + const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + const mintAmount = 100_000; + const transferAmount = 50_000; + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + await expect( + this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + NULL_ADDRESS, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ), + ).to.be.revertedWithCustomError(this.encryptedERC20, "ReceiverAddressNull"); + }); + + it("sender who is not allowed cannot transfer using a handle from another account", async function () { + const mintAmount = 100_000; + const transferAmount = 50_000; + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + const balanceHandleAlice = await this.encryptedERC20.balanceOf(this.signers.alice.address); + + await expect( + this.encryptedERC20.connect(this.signers.bob).transfer(this.signers.carol.address, balanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("sender who is not allowed cannot transferFrom using a handle from another account", async function () { + const mintAmount = 100_000; + const transferAmount = 50_000; + + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + let input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(mintAmount); + const encryptedAllowanceAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + input = this.instances.carol.createEncryptedInput(this.encryptedERC20Address, this.signers.carol.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.carol) + ["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice.address, + this.signers.carol.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + const allowanceHandleAlice = await this.encryptedERC20.allowance( + this.signers.alice.address, + this.signers.carol.address, + ); + + await expect( + this.encryptedERC20 + .connect(this.signers.bob) + .transferFrom(this.signers.alice.address, this.signers.bob.address, allowanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("cannot reencrypt errors if the account is not a participant of the transfer", async function () { + const mintAmount = 10_000; + const transferAmount = 1337; + let tx = await this.encryptedERC20.connect(this.signers.alice).mint(mintAmount); + await tx.wait(); + + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + const errorCodeHandle = await this.encryptedERC20.getErrorCodeForTransferId(DEFAULT_TRANSFER_ID); + + const { publicKey: publicKeyCarol, privateKey: privateKeyCarol } = this.instances.carol.generateKeypair(); + const eip712Carol = this.instances.carol.createEIP712(publicKeyCarol, this.encryptedERC20Address); + const signatureCarol = await this.signers.carol.signTypedData( + eip712Carol.domain, + { Reencrypt: eip712Carol.types.Reencrypt }, + eip712Carol.message, + ); + + try { + await this.instances.bob.reencrypt( + errorCodeHandle, + privateKeyCarol, + publicKeyCarol, + signatureCarol.replace("0x", ""), + this.encryptedERC20Address, + this.signers.carol.address, + ); + expect.fail( + "Expected an error to be thrown - Carol should not be able to read the error message from the transaction between Alice and Bob", + ); + } catch (error) { + if (error instanceof Error) { + expect(error.message).to.equal("User is not authorized to reencrypt this handle!"); + } + } + }); + + it("sender who is not allowed cannot approve using a handle from another account", async function () { + const amount = 100_000; + const input = this.instances.alice.createEncryptedInput(this.encryptedERC20Address, this.signers.alice.address); + input.add64(amount); + const encryptedAllowanceAmount = await input.encrypt(); + + const tx = await this.encryptedERC20 + .connect(this.signers.alice) + ["approve(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + + await tx.wait(); + + const allowanceHandleAlice = await this.encryptedERC20.allowance( + this.signers.alice.address, + this.signers.carol.address, + ); + + await expect( + this.encryptedERC20.connect(this.signers.bob).approve(this.signers.carol.address, allowanceHandleAlice), + ).to.be.revertedWithCustomError(this.encryptedERC20, "TFHESenderNotAllowed"); + }); + + it("EncryptedERC20WithErrorsMintable - only owner can mint", async function () { + await expect(this.encryptedERC20.connect(this.signers.bob).mint(1)).to.be.revertedWithCustomError( + this.encryptedERC20, + "OwnableUnauthorizedAccount", + ); + }); +}); diff --git a/test/fhevmjsMocked.ts b/test/fhevmjsMocked.ts new file mode 100644 index 0000000..0b19d1f --- /dev/null +++ b/test/fhevmjsMocked.ts @@ -0,0 +1,555 @@ +import { toBigIntBE } from "bigint-buffer"; +import { toBufferBE } from "bigint-buffer"; +import crypto from "crypto"; +import dotenv from "dotenv"; +import { Wallet, ethers } from "ethers"; +import * as fs from "fs"; +import { Keccak } from "sha3"; +import { isAddress } from "web3-validator"; + +import { insertSQL } from "./coprocessorUtils"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; + +const hre = require("hardhat"); + +const parsedEnvACL = dotenv.parse(fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl")); +const aclAdd = parsedEnvACL.ACL_CONTRACT_ADDRESS; + +enum Types { + ebool = 0, + euint4, + euint8, + euint16, + euint32, + euint64, + euint128, + eaddress, + euint256, + ebytes64, + ebytes128, + ebytes256, +} + +const sum = (arr: number[]) => arr.reduce((acc, val) => acc + val, 0); + +function bytesToBigInt(byteArray: Uint8Array): bigint { + if (!byteArray || byteArray?.length === 0) { + return BigInt(0); + } + const buffer = Buffer.from(byteArray); + const result = toBigIntBE(buffer); + return result; +} + +function createUintToUint8ArrayFunction(numBits: number) { + const numBytes = Math.ceil(numBits / 8); + return function (uint: number | bigint | boolean) { + const buffer = toBufferBE(BigInt(uint), numBytes); + + // concatenate 32 random bytes at the end of buffer to simulate encryption noise + const randomBytes = crypto.randomBytes(32); + const combinedBuffer = Buffer.concat([buffer, randomBytes]); + + let byteBuffer; + let totalBuffer; + + switch (numBits) { + case 2: // ebool takes 2 bits + byteBuffer = Buffer.from([Types.ebool]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 4: + byteBuffer = Buffer.from([Types.euint4]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 8: + byteBuffer = Buffer.from([Types.euint8]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 16: + byteBuffer = Buffer.from([Types.euint16]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 32: + byteBuffer = Buffer.from([Types.euint32]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 64: + byteBuffer = Buffer.from([Types.euint64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 128: + byteBuffer = Buffer.from([Types.euint128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 160: + byteBuffer = Buffer.from([Types.eaddress]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 256: + byteBuffer = Buffer.from([Types.euint256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 512: + byteBuffer = Buffer.from([Types.ebytes64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 1024: + byteBuffer = Buffer.from([Types.ebytes128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 2048: + byteBuffer = Buffer.from([Types.ebytes256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + default: + throw Error("Non-supported numBits"); + } + + return totalBuffer; + }; +} + +export const reencryptRequestMocked = async ( + handle: bigint, + privateKey: string, + publicKey: string, + signature: string, + contractAddress: string, + userAddress: string, +) => { + // Signature checking: + const domain = { + name: "Authorization token", + version: "1", + chainId: hre.network.config.chainId, + verifyingContract: contractAddress, + }; + const types = { + Reencrypt: [{ name: "publicKey", type: "bytes" }], + }; + const value = { + publicKey: `0x${publicKey}`, + }; + const signerAddress = ethers.verifyTypedData(domain, types, value, `0x${signature}`); + const normalizedSignerAddress = ethers.getAddress(signerAddress); + const normalizedUserAddress = ethers.getAddress(userAddress); + if (normalizedSignerAddress !== normalizedUserAddress) { + throw new Error("Invalid EIP-712 signature!"); + } + + // ACL checking + const aclFactory = await hre.ethers.getContractFactory("fhevmTemp/contracts/ACL.sol:ACL"); + const acl = aclFactory.attach(aclAdd); + const userAllowed = await acl.persistAllowed(handle, userAddress); + const contractAllowed = await acl.persistAllowed(handle, contractAddress); + + const isAllowed = userAllowed && contractAllowed; + if (!isAllowed) { + throw new Error("User is not authorized to reencrypt this handle!"); + } + if (userAddress === contractAddress) { + throw new Error("userAddress should not be equal to contractAddress when requesting reencryption!"); + } + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); +}; + +export const createEncryptedInputMocked = (contractAddress: string, userAddress: string) => { + if (!isAddress(contractAddress)) { + throw new Error("Contract address is not a valid address."); + } + + if (!isAddress(userAddress)) { + throw new Error("User address is not a valid address."); + } + + const values: bigint[] = []; + const bits: (keyof typeof ENCRYPTION_TYPES)[] = []; + return { + addBool(value: boolean | number | bigint) { + if (value == null) throw new Error("Missing value"); + if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "bigint") + throw new Error("The value must be a boolean, a number or a bigint."); + if ((typeof value !== "bigint" || typeof value !== "number") && Number(value) > 1) + throw new Error("The value must be 1 or 0."); + values.push(BigInt(value)); + bits.push(2); // ebool takes 2 bits instead of one: only exception in TFHE-rs + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add4(value: number | bigint) { + checkEncryptedValue(value, 4); + values.push(BigInt(value)); + bits.push(4); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add8(value: number | bigint) { + checkEncryptedValue(value, 8); + values.push(BigInt(value)); + bits.push(8); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add16(value: number | bigint) { + checkEncryptedValue(value, 16); + values.push(BigInt(value)); + bits.push(16); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add32(value: number | bigint) { + checkEncryptedValue(value, 32); + values.push(BigInt(value)); + bits.push(32); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add64(value: number | bigint) { + checkEncryptedValue(value, 64); + values.push(BigInt(value)); + bits.push(64); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add128(value: number | bigint) { + checkEncryptedValue(value, 128); + values.push(BigInt(value)); + bits.push(128); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addAddress(value: string) { + if (!isAddress(value)) { + throw new Error("The value must be a valid address."); + } + values.push(BigInt(value)); + bits.push(160); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add256(value: number | bigint) { + checkEncryptedValue(value, 256); + values.push(BigInt(value)); + bits.push(256); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes64(value: Uint8Array) { + if (value.length !== 64) throw Error("Uncorrect length of input Uint8Array, should be 64 for an ebytes64"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 512); + values.push(bigIntValue); + bits.push(512); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes128(value: Uint8Array) { + if (value.length !== 128) throw Error("Uncorrect length of input Uint8Array, should be 128 for an ebytes128"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 1024); + values.push(bigIntValue); + bits.push(1024); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes256(value: Uint8Array) { + if (value.length !== 256) throw Error("Uncorrect length of input Uint8Array, should be 256 for an ebytes256"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 2048); + values.push(bigIntValue); + bits.push(2048); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + getValues() { + return values; + }, + getBits() { + return bits; + }, + resetValues() { + values.length = 0; + bits.length = 0; + return this; + }, + async encrypt() { + let encrypted = Buffer.alloc(0); + + bits.map((v, i) => { + encrypted = Buffer.concat([encrypted, createUintToUint8ArrayFunction(v)(values[i])]); + }); + + const encryptedArray = new Uint8Array(encrypted); + const hash = new Keccak(256).update(Buffer.from(encryptedArray)).digest(); + + const handles = bits.map((v, i) => { + const dataWithIndex = new Uint8Array(hash.length + 1); + dataWithIndex.set(hash, 0); + dataWithIndex.set([i], hash.length); + const finalHash = new Keccak(256).update(Buffer.from(dataWithIndex)).digest(); + const dataInput = new Uint8Array(32); + dataInput.set(finalHash, 0); + dataInput.set([i, ENCRYPTION_TYPES[v], 0], 29); + return dataInput; + }); + let inputProof = "0x" + numberToHex(handles.length); // for coprocessor : numHandles + numSignersKMS + hashCT + list_handles + signatureCopro + signatureKMSSigners (total len : 1+1+32+NUM_HANDLES*32+65+65*numSignersKMS) + // for native : numHandles + numSignersKMS + list_handles + signatureKMSSigners + bundleCiphertext (total len : 1+1+NUM_HANDLES*32+65*numSignersKMS+bundleCiphertext.length) + const numSigners = +process.env.NUM_KMS_SIGNERS!; + inputProof += numberToHex(numSigners); + if (process.env.IS_COPROCESSOR === "true") { + // coprocessor + inputProof += hash.toString("hex"); + + const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); + listHandlesStr.map((handle) => (inputProof += handle)); + const listHandles = listHandlesStr.map((i) => BigInt("0x" + i)); + const sigCoproc = await computeInputSignatureCopro( + "0x" + hash.toString("hex"), + listHandles, + userAddress, + contractAddress, + ); + inputProof += sigCoproc.slice(2); + + const signaturesKMS = await computeInputSignaturesKMS( + "0x" + hash.toString("hex"), + userAddress, + contractAddress, + ); + signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); + listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); + } else { + // native + const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); + listHandlesStr.map((handle) => (inputProof += handle)); + const signaturesKMS = await computeInputSignaturesKMS( + "0x" + hash.toString("hex"), + userAddress, + contractAddress, + ); + signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); + listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); + + inputProof += encrypted.toString("hex"); + } + + return { + handles, + inputProof, + }; + }, + }; +}; + +function uint8ArrayToHexString(uint8Array: Uint8Array) { + return Array.from(uint8Array) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); +} + +function numberToHex(num: number) { + let hex = num.toString(16); + return hex.length % 2 ? "0" + hex : hex; +} + +const checkEncryptedValue = (value: number | bigint, bits: number) => { + if (value == null) throw new Error("Missing value"); + let limit; + if (bits >= 8) { + limit = BigInt(`0x${new Array(bits / 8).fill(null).reduce((v) => `${v}ff`, "")}`); + } else { + limit = BigInt(2 ** bits - 1); + } + if (typeof value !== "number" && typeof value !== "bigint") throw new Error("Value must be a number or a bigint."); + if (value > limit) { + throw new Error(`The value exceeds the limit for ${bits}bits integer (${limit.toString()}).`); + } +}; + +export const ENCRYPTION_TYPES = { + 2: 0, // ebool takes 2 bits + 4: 1, + 8: 2, + 16: 3, + 32: 4, + 64: 5, + 128: 6, + 160: 7, + 256: 8, + 512: 9, + 1024: 10, + 2048: 11, +}; + +async function computeInputSignatureCopro( + hash: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, +): Promise { + let signature: string; + const privKeySigner = process.env["PRIVATE_KEY_COPROCESSOR_ACCOUNT"]; + if (privKeySigner) { + const coprocSigner = new Wallet(privKeySigner).connect(ethers.provider); + signature = await coprocSign(hash, handlesList, userAddress, contractAddress, coprocSigner); + } else { + throw new Error(`Private key for coprocessor not found in environment variables`); + } + return signature; +} + +async function computeInputSignaturesKMS( + hash: string, + userAddress: string, + contractAddress: string, +): Promise { + const signatures: string[] = []; + const numSigners = +process.env.NUM_KMS_SIGNERS!; + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = process.env[`PRIVATE_KEY_KMS_SIGNER_${idx}`]; + if (privKeySigner) { + const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); + const signature = await kmsSign(hash, userAddress, contractAddress, kmsSigner); + signatures.push(signature); + } else { + throw new Error(`Private key for signer ${idx} not found in environment variables`); + } + } + return signatures; +} + +async function coprocSign( + hashOfCiphertext: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const inputAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.inputverifier"), + ).INPUT_VERIFIER_CONTRACT_ADDRESS; + const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; + const aclAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl"), + ).ACL_CONTRACT_ADDRESS; + + const domain = { + name: "InputVerifier", + version: "1", + chainId: chainId, + verifyingContract: inputAdd, + }; + + const types = { + CiphertextVerificationForCopro: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + handlesList: handlesList, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} + +async function kmsSign( + hashOfCiphertext: string, + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const kmsVerifierAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.kmsverifier"), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; + const aclAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl"), + ).ACL_CONTRACT_ADDRESS; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsVerifierAdd, + }; + + const types = { + CiphertextVerificationForKMS: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} diff --git a/test/governance/Comp.fixture.ts b/test/governance/Comp.fixture.ts new file mode 100644 index 0000000..ef6d4c7 --- /dev/null +++ b/test/governance/Comp.fixture.ts @@ -0,0 +1,64 @@ +import { ethers } from "hardhat"; + +import type { TestComp } from "../../types"; +import { reencryptEuint64 } from "../reencrypt"; +import { Signers } from "../signers"; +import { FhevmInstances } from "../types"; + +export async function deployCompFixture(signers: Signers): Promise { + const contractFactory = await ethers.getContractFactory("TestComp"); + const contract = await contractFactory.connect(signers.alice).deploy(signers.alice.address); + await contract.waitForDeployment(); + return contract; +} + +export async function transferTokensAndDelegate( + signers: Signers, + instances: FhevmInstances, + transferAmount: bigint, + account: string, + delegate: string, + comp: TestComp, + compAddress: string, +): Promise { + const input = instances.alice.createEncryptedInput(compAddress, signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + let tx = await comp + .connect(signers.alice) + ["transfer(address,bytes32,bytes)"]( + signers[account as keyof Signers], + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx.wait(); + + tx = await comp.connect(signers[account as keyof Signers]).delegate(signers[delegate as keyof Signers].address); + await tx.wait(); +} + +export async function reencryptCurrentVotes( + signers: Signers, + instances: FhevmInstances, + account: string, + comp: TestComp, + compAddress: string, +): Promise { + const voteHandle = await comp.getCurrentVotes(signers[account as keyof Signers].address); + const vote = await reencryptEuint64(signers, instances, account, voteHandle, compAddress); + return vote; +} + +export async function reencryptPriorVotes( + signers: Signers, + instances: FhevmInstances, + account: string, + blockNumber: number, + comp: TestComp, + compAddress: string, +): Promise { + const voteHandle = await comp.getPriorVotes(signers[account as keyof Signers].address, blockNumber); + const vote = await reencryptEuint64(signers, instances, account, voteHandle, compAddress); + return vote; +} diff --git a/test/governance/Comp.test.ts b/test/governance/Comp.test.ts new file mode 100644 index 0000000..9f046a0 --- /dev/null +++ b/test/governance/Comp.test.ts @@ -0,0 +1,445 @@ +import { expect } from "chai"; +import { parseUnits } from "ethers"; +import { ethers, network } from "hardhat"; + +import { reencryptBalance } from "../encryptedERC20/EncryptedERC20.fixture"; +import { createInstances } from "../instance"; +import { reencryptEuint64 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { waitNBlocks } from "../utils"; +import { deployCompFixture, reencryptCurrentVotes, reencryptPriorVotes } from "./Comp.fixture"; +import { delegateBySig } from "./DelegateBySig"; + +describe("Comp", function () { + before(async function () { + await initSigners(3); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const contract = await deployCompFixture(this.signers); + this.compAddress = await contract.getAddress(); + this.comp = contract; + this.instances = await createInstances(this.signers); + }); + + it("should transfer tokens", async function () { + const transferAmount = parseUnits(String(2_000_000), 6); + + const input = this.instances.alice.createEncryptedInput(this.compAddress, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + const tx = await this.comp["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + // Decrypt Alice's balance + expect(await reencryptBalance(this.signers, this.instances, "alice", this.comp, this.compAddress)).to.equal( + parseUnits(String(8_000_000), 6), + ); + + // Decrypt Bob's balance + expect(await reencryptBalance(this.signers, this.instances, "bob", this.comp, this.compAddress)).to.equal( + parseUnits(String(2_000_000), 6), + ); + }); + + it("can delegate tokens on-chain", async function () { + const tx = await this.comp.connect(this.signers.alice).delegate(this.signers.bob.address); + await tx.wait(); + + const latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect( + await reencryptPriorVotes(this.signers, this.instances, "bob", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(parseUnits(String(10_000_000), 6)); + + // Verify the two functions return the same. + expect( + await reencryptPriorVotes(this.signers, this.instances, "bob", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(await reencryptCurrentVotes(this.signers, this.instances, "bob", this.comp, this.compAddress)); + }); + + it("can delegate votes via delegateBySig if signature is valid", async function () { + const delegatee = this.signers.bob; + const nonce = 0; + let latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry = block!.timestamp + 100; + const [v, r, s] = await delegateBySig(this.signers.alice, delegatee.address, this.comp, nonce, expiry); + + const tx = await this.comp.connect(this.signers.alice).delegateBySig(delegatee, nonce, expiry, v, r, s); + await tx.wait(); + + latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect( + await reencryptPriorVotes(this.signers, this.instances, "bob", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(parseUnits(String(10_000_000), 6)); + + // Verify the two functions return the same. + expect( + await reencryptPriorVotes(this.signers, this.instances, "bob", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(await reencryptCurrentVotes(this.signers, this.instances, "bob", this.comp, this.compAddress)); + }); + + it("cannot delegate votes to self but it gets removed once the tokens are transferred", async function () { + let tx = await this.comp.connect(this.signers.alice).delegate(this.signers.alice.address); + await tx.wait(); + + let latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect( + await reencryptPriorVotes(this.signers, this.instances, "alice", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(parseUnits(String(10_000_000), 6)); + + const transferAmount = parseUnits(String(10_000_000), 6); + const input = this.instances.alice.createEncryptedInput(this.compAddress, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + tx = await this.comp + .connect(this.signers.alice) + ["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect( + await reencryptPriorVotes(this.signers, this.instances, "alice", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(0); + }); + + it("cannot delegate votes if nonce is invalid", async function () { + const delegatee = this.signers.bob; + const nonce = 0; + let latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry = block!.timestamp + 100; + const [v, r, s] = await delegateBySig(this.signers.alice, delegatee.address, this.comp, nonce, expiry); + + const tx = await this.comp.connect(this.signers.alice).delegateBySig(delegatee, nonce, expiry, v, r, s); + await tx.wait(); + + // Cannot reuse same nonce when delegating by sig + await expect(this.comp.delegateBySig(delegatee, nonce, expiry, v, r, s)).to.be.revertedWith( + "Comp::delegateBySig: invalid nonce", + ); + }); + + it("cannot delegate votes if signer is invalid", async function () { + const delegatee = this.signers.bob; + const nonce = 0; + let latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry = block!.timestamp + 100; + const [v, r, s] = await delegateBySig(this.signers.alice, delegatee.address, this.comp, nonce, expiry); + + // Cannot use invalid signature when delegating by sig + await expect(this.comp.delegateBySig(delegatee, nonce, expiry, 30, r, s)).to.be.revertedWith( + "Comp::delegateBySig: invalid signature", + ); + }); + + it("cannot delegate votes if signature has expired", async function () { + const delegatee = this.signers.bob; + const nonce = 0; + let latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry = block!.timestamp + 100; + const [v, r, s] = await delegateBySig(this.signers.alice, delegatee.address, this.comp, nonce, expiry); + + ethers.provider.send("evm_increaseTime", ["0xffff"]); + + await expect(this.comp.connect(delegatee).delegateBySig(delegatee, nonce, expiry, v, r, s)).to.be.revertedWith( + "Comp::delegateBySig: signature expired", + ); + }); + + it("cannot request votes if blocktime is equal to current blocktime", async function () { + let blockNumber = await ethers.provider.getBlockNumber(); + + await expect(this.comp.getPriorVotes(this.signers.alice, blockNumber + 1)).to.be.revertedWithCustomError( + this.comp, + "BlockNumberEqualOrHigherThanCurrentBlock", + ); + + const newAllowedContract = "0x9d3e06a2952dc49EDCc73e41C76645797fC53967"; + + const tx = await this.comp.connect(this.signers.alice).setGovernor(this.signers.bob); + await tx.wait(); + + blockNumber = await ethers.provider.getBlockNumber(); + + await expect( + this.comp.connect(this.signers.bob).getPriorVotesForGovernor(this.signers.alice, blockNumber + 1), + ).to.be.revertedWithCustomError(this.comp, "BlockNumberEqualOrHigherThanCurrentBlock"); + }); + + it("users can request past votes getPriorVotes", async function () { + // Alice transfers 1M tokens to Bob, 1M tokens to Carol, 1M tokens to Dave + const transferAmount = parseUnits(String(1_000_000), 6); + + const input = this.instances.alice.createEncryptedInput(this.compAddress, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + let tx = await this.comp["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + tx = await this.comp["transfer(address,bytes32,bytes)"]( + this.signers.carol.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + tx = await this.comp["transfer(address,bytes32,bytes)"]( + this.signers.dave.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + tx = await this.comp.connect(this.signers.bob).delegate(this.signers.dave.address); + await tx.wait(); + + const firstCheckPointBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + tx = await this.comp.connect(this.signers.carol).delegate(this.signers.dave.address); + await tx.wait(); + + const secondCheckPointBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect( + await reencryptPriorVotes( + this.signers, + this.instances, + "dave", + firstCheckPointBlockNumber, + this.comp, + this.compAddress, + ), + ).to.be.equal(parseUnits(String(1_000_000), 6)); + + expect( + await reencryptPriorVotes( + this.signers, + this.instances, + "dave", + secondCheckPointBlockNumber, + this.comp, + this.compAddress, + ), + ).to.be.equal(parseUnits(String(2_000_000), 6)); + }); + + it("only governor contract can call getPriorVotes", async function () { + await expect( + this.comp.getPriorVotesForGovernor("0xE359a77c3bFE58792FB167D05720e37032A1e520", 0), + ).to.be.revertedWithCustomError(this.comp, "GovernorInvalid"); + }); + + it("only owner can set governor contract", async function () { + const newAllowedContract = "0x9d3e06a2952dc49EDCc73e41C76645797fC53967"; + await expect(this.comp.connect(this.signers.bob).setGovernor(newAllowedContract)) + .to.be.revertedWithCustomError(this.comp, "OwnableUnauthorizedAccount") + .withArgs(this.signers.bob.address); + }); + + it("getCurrentVote/getPriorVotes without any vote cannot be decrypted", async function () { + // 1. If no checkpoint exists using getCurrentVotes + let currentVoteHandle = await this.comp.connect(this.signers.bob).getCurrentVotes(this.signers.bob.address); + expect(currentVoteHandle).to.be.eq(BigInt(0)); + + await expect( + reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), + ).to.be.rejectedWith("Handle is not initialized"); + + // 2. If no checkpoint exists using getPriorVotes + let latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + currentVoteHandle = await this.comp + .connect(this.signers.bob) + .getPriorVotes(this.signers.bob.address, latestBlockNumber); + + // It is an encrypted constant that is not reencryptable by Bob. + expect(currentVoteHandle).not.to.be.eq(BigInt(0)); + + await expect( + reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), + ).to.be.rejectedWith("Invalid contract address."); + + // 3. If a checkpoint exists using getPriorVotes but block.number < block of first checkpoint + latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + const tx = await this.comp.connect(this.signers.alice).delegate(this.signers.bob.address); + await tx.wait(); + + currentVoteHandle = await this.comp + .connect(this.signers.bob) + .getPriorVotes(this.signers.bob.address, latestBlockNumber); + + // It is an encrypted constant that is not reencryptable by Bob. + expect(currentVoteHandle).not.to.be.eq(BigInt(0)); + + await expect( + reencryptEuint64(this.signers, this.instances, "bob", currentVoteHandle, this.comp), + ).to.be.rejectedWith("Invalid contract address."); + }); + + it("can do multiple checkpoints and access the values when needed", async function () { + let i = 0; + + const blockNumbers = []; + + while (i < 20) { + let tx = await this.comp.connect(this.signers.alice).delegate(this.signers.alice.address); + await tx.wait(); + blockNumbers.push(await ethers.provider.getBlockNumber()); + + tx = await this.comp.connect(this.signers.alice).delegate(this.signers.carol.address); + await tx.wait(); + blockNumbers.push(await ethers.provider.getBlockNumber()); + i++; + } + + waitNBlocks(1); + + // There are 40 checkpoints for Alice and 39 checkpoints for Carol + expect(await this.comp.numCheckpoints(this.signers.alice.address)).to.eq(BigInt(40)); + expect(await this.comp.numCheckpoints(this.signers.carol.address)).to.eq(BigInt(39)); + + i = 0; + + while (i < 40) { + if (blockNumbers[i] % 2 === 0) { + expect( + await reencryptPriorVotes( + this.signers, + this.instances, + "alice", + blockNumbers[i], + this.comp, + this.compAddress, + ), + ).to.be.eq(parseUnits(String(10_000_000), 6)); + } else { + expect( + await reencryptPriorVotes( + this.signers, + this.instances, + "carol", + blockNumbers[i], + this.comp, + this.compAddress, + ), + ).to.be.eq(parseUnits(String(10_000_000), 6)); + } + i++; + } + }); + + it("governor address can access votes for any account", async function () { + // Bob becomes the governor address. + let tx = await this.comp.connect(this.signers.alice).setGovernor(this.signers.bob.address); + await tx.wait(); + + // Alice delegates her votes to Carol. + tx = await this.comp.connect(this.signers.alice).delegate(this.signers.carol.address); + await tx.wait(); + + const latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + await waitNBlocks(1); + + // Bob, the governor address, gets the prior votes of Carol. + // @dev It is not possible to catch the return value since it is not a view function. + // GovernorAlphaZama.test.ts contains tests that use this function. + await this.comp + .connect(this.signers.bob) + .getPriorVotesForGovernor(this.signers.carol.address, latestBlockNumber + 1); + }); + + it("different voters can delegate to same delegatee", async function () { + const transferAmount = parseUnits(String(2_000_000), 6); + + const input = this.instances.alice.createEncryptedInput(this.compAddress, this.signers.alice.address); + input.add64(transferAmount); + const encryptedTransferAmount = await input.encrypt(); + + let tx = await this.comp["transfer(address,bytes32,bytes)"]( + this.signers.bob.address, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + + await tx.wait(); + + tx = await this.comp.connect(this.signers.alice).delegate(this.signers.carol); + await tx.wait(); + + tx = await this.comp.connect(this.signers.bob).delegate(this.signers.carol); + await tx.wait(); + + const latestBlockNumber = await ethers.provider.getBlockNumber(); + await waitNBlocks(1); + + expect(await reencryptCurrentVotes(this.signers, this.instances, "carol", this.comp, this.compAddress)).to.equal( + parseUnits(String(10_000_000), 6), + ); + + expect( + await reencryptPriorVotes(this.signers, this.instances, "carol", latestBlockNumber, this.comp, this.compAddress), + ).to.equal(await reencryptCurrentVotes(this.signers, this.instances, "carol", this.comp, this.compAddress)); + }); + + // TODO: fix issue with mining + it.skip("number of checkpoints is incremented once per block, even when written multiple times in same block", async function () { + await network.provider.send("evm_setAutomine", [false]); + await network.provider.send("evm_setIntervalMining", [0]); + + // do two checkpoints in same block + const tx1 = this.comp.connect(this.signers.alice).delegate(this.signers.bob); + const tx2 = this.comp.connect(this.signers.alice).delegate(this.signers.carol); + + await network.provider.send("evm_mine"); + await network.provider.send("evm_setAutomine", [true]); + await Promise.all([tx1, tx2]); + + expect(await this.comp.numCheckpoints(this.signers.alice.address)).to.be.equal(0n); + expect(await this.comp.numCheckpoints(this.signers.bob.address)).to.be.equal(1n); + expect(await this.comp.numCheckpoints(this.signers.carol.address)).to.be.equal(1n); + + expect(await reencryptCurrentVotes(this.signers, this.instances, "bob", this.comp, this.compAddress)).to.equal(0); + + expect(await reencryptCurrentVotes(this.signers, this.instances, "carol", this.comp, this.compAddress)).to.equal( + parseUnits(String(10_000_000), 6), + ); + }); +}); diff --git a/test/dao/Timelock.ts b/test/governance/CompoundTimelock.test.ts similarity index 94% rename from test/dao/Timelock.ts rename to test/governance/CompoundTimelock.test.ts index 432edda..5b7f6c1 100644 --- a/test/dao/Timelock.ts +++ b/test/governance/CompoundTimelock.test.ts @@ -1,28 +1,29 @@ import { expect } from "chai"; import { ethers, network } from "hardhat"; -import { createInstances } from "../instance"; import { getSigners, initSigners } from "../signers"; -import { createTransaction, waitNBlocks } from "../utils"; -import { deployCompFixture } from "./Comp.fixture"; -import { deployGovernorZamaFixture, deployTimelockFixture } from "./GovernorZama.fixture"; +import { deployTimelockFixture } from "./GovernorAlphaZama.fixture"; -describe("Timelock", function () { +describe("CompoundTimelock", function () { before(async function () { - await initSigners(); + await initSigners(3); this.signers = await getSigners(); }); beforeEach(async function () { - this.timelock = await deployTimelockFixture(this.signers.alice); + this.timelock = await deployTimelockFixture(this.signers.alice.address); }); it("non-timelock account could not call setPendingAdmin", async function () { - await expect(this.timelock.setPendingAdmin(this.signers.bob)).to.throw; + await expect(this.timelock.setPendingAdmin(this.signers.bob)).to.be.revertedWith( + "Timelock::setPendingAdmin: Call must come from Timelock.", + ); }); it("non-timelock account could not call setDelay", async function () { - await expect(this.timelock.setDelay(60 * 60 * 24 * 3)).to.throw; + await expect(this.timelock.setDelay(60 * 60 * 24 * 3)).to.be.revertedWith( + "Timelock::setDelay: Call must come from Timelock.", + ); }); it("setDelay could only be called with a delay between MINIMUM_DELAY and MAXIMUM_DELAY", async function () { diff --git a/test/dao/DelegateBySig.ts b/test/governance/DelegateBySig.ts similarity index 96% rename from test/dao/DelegateBySig.ts rename to test/governance/DelegateBySig.ts index 62ef43d..bc0fe7c 100644 --- a/test/dao/DelegateBySig.ts +++ b/test/governance/DelegateBySig.ts @@ -4,7 +4,7 @@ import { Address } from "hardhat-deploy/types"; import type { Comp } from "../../types"; -export const delegateBySigSignature = async ( +export const delegateBySig = async ( _signer: HardhatEthersSigner, _delegatee: Address, _comp: Comp, diff --git a/test/governance/GovernorAlphaZama.fixture.ts b/test/governance/GovernorAlphaZama.fixture.ts new file mode 100644 index 0000000..ac27117 --- /dev/null +++ b/test/governance/GovernorAlphaZama.fixture.ts @@ -0,0 +1,48 @@ +import { ethers } from "hardhat"; + +import type { CompoundTimelock, TestGovernorAlphaZama } from "../../types"; +import { reencryptEbool, reencryptEuint64 } from "../reencrypt"; +import { Signers, getSigners } from "../signers"; +import { FhevmInstances } from "../types"; + +export async function deployTimelockFixture(admin: string): Promise { + const signers = await getSigners(); + const timelockFactory = await ethers.getContractFactory("CompoundTimelock"); + const timelock = await timelockFactory.connect(signers.alice).deploy(admin, 60 * 60 * 24 * 2); + await timelock.waitForDeployment(); + return timelock; +} + +export async function deployGovernorAlphaZamaFixture( + signers: Signers, + compAddress: string, + timelockAddress: string, +): Promise { + // @dev We use 5 only for testing purpose. + // DO NOT use this value in production. + const votingPeriod = 5; + const governorFactory = await ethers.getContractFactory("TestGovernorAlphaZama"); + const governor = await governorFactory + .connect(signers.alice) + .deploy(signers.alice.address, timelockAddress, compAddress, votingPeriod); + await governor.waitForDeployment(); + return governor; +} + +export async function reencryptVoteReceipt( + signers: Signers, + instances: FhevmInstances, + proposalId: bigint, + account: string, + governor: TestGovernorAlphaZama, + governorAddress: string, +): Promise<[boolean, boolean, bigint]> { + const [hasVoted, supportHandle, voteHandle] = await governor.getReceipt( + proposalId, + signers[account as keyof Signers].address, + ); + const support = await reencryptEbool(signers, instances, account, supportHandle, governorAddress); + const vote = await reencryptEuint64(signers, instances, account, voteHandle, governorAddress); + + return [hasVoted, support, vote]; +} diff --git a/test/governance/GovernorAlphaZama.test.ts b/test/governance/GovernorAlphaZama.test.ts new file mode 100644 index 0000000..ba41492 --- /dev/null +++ b/test/governance/GovernorAlphaZama.test.ts @@ -0,0 +1,1080 @@ +import { expect } from "chai"; +import { parseUnits } from "ethers"; +import { ethers, network } from "hardhat"; + +import { awaitAllDecryptionResults } from "../asyncDecrypt"; +import { createInstances } from "../instance"; +import { getSigners, initSigners } from "../signers"; +import { mineNBlocks } from "../utils"; +import { deployCompFixture, transferTokensAndDelegate } from "./Comp.fixture"; +import { + deployGovernorAlphaZamaFixture, + deployTimelockFixture, + reencryptVoteReceipt, +} from "./GovernorAlphaZama.fixture"; + +describe("GovernorAlphaZama", function () { + before(async function () { + await initSigners(4); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const contract = await deployCompFixture(this.signers); + this.comp = contract; + this.compAddress = await contract.getAddress(); + this.instances = await createInstances(this.signers); + + const precomputedGovernorAddress = ethers.getCreateAddress({ + from: this.signers.alice.address, + nonce: (await this.signers.alice.getNonce()) + 1, + }); + + const timelock = await deployTimelockFixture(precomputedGovernorAddress); + this.timelock = timelock; + this.timelockAddress = await timelock.getAddress(); + + const governor = await deployGovernorAlphaZamaFixture(this.signers, this.compAddress, this.timelockAddress); + this.governor = governor; + this.governorAddress = await governor.getAddress(); + + const tx = await this.comp.setGovernor(this.governorAddress); + await tx.wait(); + }); + + it("can propose a vote that becomes active if votes match the token threshold", async function () { + const transferAmount = parseUnits(String(500_000), 6); + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + const tx = await this.governor + .connect(this.signers.bob) + .propose(targets, values, signatures, calldatas, description); + + await tx.wait(); + + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + let proposalInfo = await this.governor.getProposalInfo(proposalId); + + // @dev .to.eql is used to compare array elements + expect(proposalInfo.proposer).to.equal(this.signers.bob.address); + expect(proposalInfo.targets).to.eql(targets); + expect(proposalInfo.signatures).to.eql(signatures); + expect(proposalInfo.calldatas).to.eql(calldatas); + // 1 ==> PendingThresholdVerification + expect(proposalInfo.state).to.equal(1); + + await awaitAllDecryptionResults(); + + proposalInfo = await this.governor.getProposalInfo(proposalId); + // 3 ==> Active + expect(proposalInfo.state).to.equal(3); + }); + + it("anyone can propose a vote but it is rejected if votes are below the token threshold", async function () { + const transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - BigInt(1); + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + let proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.proposer).to.equal(this.signers.bob.address); + + // 1 ==> PendingThresholdVerification + expect(proposalInfo.state).to.equal(1); + await awaitAllDecryptionResults(); + + proposalInfo = await this.governor.getProposalInfo(proposalId); + + await awaitAllDecryptionResults(); + + // 2 ==> Rejected + expect(proposalInfo.state).to.equal(2); + }); + + it("multiple users can vote and the vote succeeds if forVotes > quorum", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = parseUnits(String(200_000), 6); + + // Bob and Carol receive 200k tokens and delegate to themselves. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "carol", + "carol", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob and Carol vote for + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + input = this.instances.carol.createEncryptedInput(this.governorAddress, this.signers.carol.address); + input.addBool(true); + encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.carol) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Bob/Carol can reeencrypt his/her receipt + let [hasVoted, support, votes] = await reencryptVoteReceipt( + this.signers, + this.instances, + proposalId, + "bob", + this.governor, + this.governorAddress, + ); + + expect(hasVoted).to.be.eq(true); + expect(support).to.be.eq(true); + expect(votes).to.be.eq(transferAmount); + + [hasVoted, support, votes] = await reencryptVoteReceipt( + this.signers, + this.instances, + proposalId, + "carol", + this.governor, + this.governorAddress, + ); + + expect(hasVoted).to.be.eq(true); + expect(support).to.be.eq(true); + expect(votes).to.be.eq(transferAmount); + + // Mine blocks + await mineNBlocks(3); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + let proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(parseUnits(String(0), 6)); + expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); + // 4 ==> Succeeded + expect(proposalInfo.state).to.equal(4); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(transferAmount * BigInt(2)); + expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); + // 7 ==> Succeeded + expect(proposalInfo.state).to.equal(7); + + // QUEUING + tx = await this.governor.queue(proposalId); + await tx.wait(); + + proposalInfo = await this.governor.getProposalInfo(proposalId); + // 8 ==> Queued + expect(proposalInfo.state).to.equal(8); + const eta = proposalInfo.eta; + + // EXECUTE + await ethers.provider.send("evm_setNextBlockTimestamp", [eta.toString()]); + tx = await this.governor.execute(proposalId); + await tx.wait(); + + proposalInfo = await this.governor.getProposalInfo(proposalId); + // 10 ==> Executed + expect(proposalInfo.state).to.equal(10); + }); + + it("vote is defeated if forVotes < quorum", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = (await this.governor.QUORUM_VOTES()) - BigInt(1); + + // Bob receives enough to create a proposal but not enough to match the quorum. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Bob reeencrypts his receipt + let [hasVoted, support, votes] = await reencryptVoteReceipt( + this.signers, + this.instances, + proposalId, + "bob", + this.governor, + this.governorAddress, + ); + + expect(hasVoted).to.be.eq(true); + expect(support).to.be.eq(true); + expect(votes).to.be.eq(transferAmount); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + let proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(parseUnits(String(0), 6)); + expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); + // 4 ==> Succeeded + expect(proposalInfo.state).to.equal(4); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(transferAmount); + expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); + + // 6 ==> Defeated + expect(proposalInfo.state).to.equal(6); + }); + + it("vote is rejected if forVotes < againstVotes", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmountFor = parseUnits(String(500_000), 6); + const transferAmountAgainst = parseUnits(String(500_000), 6) + BigInt(1); + + // Bob and Carol receive 200k tokens and delegate to themselves. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmountFor, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmountAgainst, + "carol", + "carol", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob votes for but Carol votes against + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + input = this.instances.carol.createEncryptedInput(this.governorAddress, this.signers.carol.address); + input.addBool(false); + encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.carol) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Bob/Carol can reeencrypt his/her receipt + let [hasVoted, support, votes] = await reencryptVoteReceipt( + this.signers, + this.instances, + proposalId, + "bob", + this.governor, + this.governorAddress, + ); + + expect(hasVoted).to.be.eq(true); + expect(support).to.be.eq(true); + expect(votes).to.be.eq(transferAmountFor); + + [hasVoted, support, votes] = await reencryptVoteReceipt( + this.signers, + this.instances, + proposalId, + "carol", + this.governor, + this.governorAddress, + ); + + expect(hasVoted).to.be.eq(true); + expect(support).to.be.eq(false); + expect(votes).to.be.eq(transferAmountAgainst); + + // Mine blocks + await mineNBlocks(3); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + let proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(parseUnits(String(0), 6)); + expect(proposalInfo.againstVotes).to.be.eq(parseUnits(String(0), 6)); + // 4 ==> Succeeded + expect(proposalInfo.state).to.equal(4); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + proposalInfo = await this.governor.getProposalInfo(proposalId); + expect(proposalInfo.forVotes).to.be.eq(transferAmountFor); + expect(proposalInfo.againstVotes).to.be.eq(transferAmountAgainst); + // 6 ==> Defeated + expect(proposalInfo.state).to.equal(6); + }); + + it("could not deploy timelock contract if delay is below 2 days or above 31 days", async function () { + const timelockFactory = await ethers.getContractFactory("CompoundTimelock"); + + if (network.name === "hardhat") { + await expect( + timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 1), + ).to.be.revertedWith("Timelock::constructor: Delay must exceed minimum delay."); // 1 day < 2 days + await expect( + timelockFactory.connect(this.signers.alice).deploy(this.signers.alice.address, 60 * 60 * 24 * 31), + ).to.be.revertedWith("Timelock::setDelay: Delay must not exceed maximum delay."); // 31 days > 30 days + } + }); + + it("only owner could queue setTimelockPendingAdmin then execute it, and then acceptTimelockAdmin", async function () { + const latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry = block!.timestamp + 60 * 60 * 24 * 2 + 60; + + const tx = await this.governor.queueSetTimelockPendingAdmin(this.signers.bob, expiry); + await tx.wait(); + + if (network.name === "hardhat") { + // hardhat cheatcodes are available only in mocked mode + await expect(this.governor.executeSetTimelockPendingAdmin(this.signers.bob, expiry)).to.be.revertedWith( + "Timelock::executeTransaction: Transaction hasn't surpassed time lock.", + ); + + await expect( + this.governor.connect(this.signers.carol).queueSetTimelockPendingAdmin(this.signers.bob, expiry), + ).to.be.revertedWithCustomError(this.governor, "OwnableUnauthorizedAccount"); + + await ethers.provider.send("evm_increaseTime", ["0x2a33c"]); + + await expect( + this.governor.connect(this.signers.carol).executeSetTimelockPendingAdmin(this.signers.bob, expiry), + ).to.be.revertedWithCustomError(this.governor, "OwnableUnauthorizedAccount"); + + const tx3 = await this.governor.executeSetTimelockPendingAdmin(this.signers.bob, expiry); + await tx3.wait(); + + await expect(this.timelock.acceptAdmin()).to.be.revertedWith( + "Timelock::acceptAdmin: Call must come from pendingAdmin.", + ); + + const tx4 = await this.timelock.connect(this.signers.bob).acceptAdmin(); + await tx4.wait(); + + const latestBlockNumber = await ethers.provider.getBlockNumber(); + const block = await ethers.provider.getBlock(latestBlockNumber); + const expiry2 = block!.timestamp + 60 * 60 * 24 * 2 + 60; + const timeLockAdd = await this.timelock.getAddress(); + const callData = ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.governorAddress]); + const tx5 = await this.timelock + .connect(this.signers.bob) + .queueTransaction(timeLockAdd, 0, "setPendingAdmin(address)", callData, expiry2); + await tx5.wait(); + await ethers.provider.send("evm_increaseTime", ["0x2a33c"]); + + const tx6 = await this.timelock + .connect(this.signers.bob) + .executeTransaction(timeLockAdd, 0, "setPendingAdmin(address)", callData, expiry2); + await tx6.wait(); + + await expect(this.governor.connect(this.signers.bob).acceptTimelockAdmin()).to.be.revertedWithCustomError( + this.governor, + "OwnableUnauthorizedAccount", + ); + + const tx7 = await this.governor.acceptTimelockAdmin(); + await tx7.wait(); + expect(await this.timelock.admin()).to.eq(this.governorAddress); + } + }); + + it("all arrays of a proposal should be of same length, non null and less than max operations", async function () { + let targets = [this.signers.bob.address]; + let values = ["0"]; + let signatures = ["getBalanceOf(address)"]; + let calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + let description = "description"; + + const invalidTargets = [this.signers.bob.address, this.signers.carol.address]; + await expect( + this.governor.connect(this.signers.alice).propose(invalidTargets, values, signatures, calldatas, description), + ).to.be.revertedWithCustomError(this.governor, "LengthsDoNotMatch"); + + const invalidValues = ["0", "0"]; + await expect( + this.governor.connect(this.signers.alice).propose(targets, invalidValues, signatures, calldatas, description), + ).to.be.revertedWithCustomError(this.governor, "LengthsDoNotMatch"); + + const invalidSignatures = ["getBalanceOf(address)", "getBalanceOf(address)"]; + await expect( + this.governor.connect(this.signers.alice).propose(targets, values, invalidSignatures, calldatas, description), + ).to.be.revertedWithCustomError(this.governor, "LengthsDoNotMatch"); + + const invalidCalldatas = [ + ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address]), + ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address]), + ]; + + await expect( + this.governor.connect(this.signers.alice).propose(targets, values, signatures, invalidCalldatas, description), + ).to.be.revertedWithCustomError(this.governor, "LengthsDoNotMatch"); + + await expect( + this.governor.connect(this.signers.alice).propose([], [], [], [], description), + ).to.be.revertedWithCustomError(this.governor, "LengthIsNull"); + + await expect( + this.governor + .connect(this.signers.alice) + .propose( + new Array(11).fill(this.signers.alice), + new Array(11).fill("0"), + new Array(11).fill("getBalanceOf(address)"), + new Array(11).fill(calldatas[0]), + description, + ), + ).to.be.revertedWithCustomError(this.governor, "LengthAboveMaxOperations"); + }); + + it("only gateway can call gateway functions", async function () { + await expect(this.governor.connect(this.signers.bob).callbackInitiateProposal(1, true)).to.be.reverted; + await expect(this.governor.connect(this.signers.bob).callbackVoteDecryption(1, 10, 10)).to.be.reverted; + }); + + it("only owner can call owner functions", async function () { + await expect(this.governor.connect(this.signers.bob).acceptTimelockAdmin()).to.be.revertedWithCustomError( + this.governor, + "OwnableUnauthorizedAccount", + ); + + await expect( + this.governor.connect(this.signers.bob).executeSetTimelockPendingAdmin(this.signers.bob.address, 1111), + ).to.be.revertedWithCustomError(this.governor, "OwnableUnauthorizedAccount"); + + await expect( + this.governor.connect(this.signers.bob).queueSetTimelockPendingAdmin(this.signers.bob.address, 1111), + ).to.be.revertedWithCustomError(this.governor, "OwnableUnauthorizedAccount"); + }); + + it("only owner or proposer can cancel proposal", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // @dev ProposalId starts at 1. + await expect(this.governor.connect(this.signers.carol).cancel(1)).to.be.revertedWithCustomError( + this.governor, + "OwnableUnauthorizedAccount", + ); + }); + + it("proposer cannot make a new proposal while he still has an already pending or active proposal", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + await expect( + this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description), + ).to.be.revertedWithCustomError(this.governor, "ProposerHasAnotherProposal"); + }); + + it("cannot queue twice or execute before queuing", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + // Bob receives 400k tokens and delegates to himself. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob casts a vote + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + + // QUEUING + // @dev Cannot execute before queuing. + await expect(this.governor.execute(proposalId)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + + tx = await this.governor.queue(proposalId); + await tx.wait(); + + // @dev Cannot queue twice. + await expect(this.governor.queue(proposalId)).to.be.revertedWithCustomError(this.governor, "ProposalStateInvalid"); + }); + + it("cannot cancel if state is Rejected/Defeated/Executed/Canceled", async function () { + let transferAmount = (await this.governor.PROPOSAL_THRESHOLD()) - BigInt(1); + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + + // CANNOT CANCEL IF REJECTED + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + await awaitAllDecryptionResults(); + + let proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + await expect(this.governor.connect(this.signers.bob).cancel(proposalId)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + + // CANNOT CANCEL IF DEFEATED + transferAmount = (await this.governor.QUORUM_VOTES()) - BigInt(1); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "carol", + "carol", + this.comp, + this.compAddress, + ); + + tx = await this.governor.connect(this.signers.carol).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + await awaitAllDecryptionResults(); + + proposalId = await this.governor.latestProposalIds(this.signers.carol.address); + + let input = this.instances.carol.createEncryptedInput(this.governorAddress, this.signers.carol.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.carol) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + await awaitAllDecryptionResults(); + await expect(this.governor.connect(this.signers.carol).cancel(proposalId)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + + // CANNOT CANCEL IF EXECUTED + transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "dave", + "dave", + this.comp, + this.compAddress, + ); + + tx = await this.governor.connect(this.signers.dave).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + await awaitAllDecryptionResults(); + + proposalId = await this.governor.latestProposalIds(this.signers.dave.address); + + input = this.instances.dave.createEncryptedInput(this.governorAddress, this.signers.dave.address); + input.addBool(true); + encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.dave) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + await awaitAllDecryptionResults(); + + tx = await this.governor.queue(proposalId); + await tx.wait(); + + const eta = (await this.governor.getProposalInfo(proposalId)).eta; + + // EXECUTE + await ethers.provider.send("evm_setNextBlockTimestamp", [eta.toString()]); + tx = await this.governor.execute(proposalId); + await tx.wait(); + + await expect(this.governor.connect(this.signers.dave).cancel(proposalId)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + + // CANNOT CANCEL TWICE + tx = await this.governor.connect(this.signers.carol).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + proposalId = await this.governor.latestProposalIds(this.signers.carol.address); + + tx = await this.governor.connect(this.signers.carol).cancel(proposalId); + await tx.wait(); + await expect(this.governor.connect(this.signers.carol).cancel(proposalId)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + }); + + it("cancel function clears the timelock if the proposal is queued", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob votes for + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + + // QUEUING + tx = await this.governor.queue(proposalId); + await tx.wait(); + + // @dev Alice is the governor's owner. + tx = await this.governor.connect(this.signers.alice).cancel(proposalId); + await tx.wait(); + + // 5 ==> Canceled + expect((await this.governor.getProposalInfo(proposalId)).state).to.equal(5); + }); + + it("cannot request vote decryption if state is not Active or if endBlock >= block.number", async function () { + await expect(this.governor.connect(this.signers.dave).requestVoteDecryption(0)).to.be.revertedWithCustomError( + this.governor, + "ProposalStateInvalid", + ); + + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob votes for + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks but not enough + await mineNBlocks(3); + + await expect( + this.governor.connect(this.signers.dave).requestVoteDecryption(proposalId), + ).to.be.revertedWithCustomError(this.governor, "ProposalStateStillActive"); + }); + + it("cannot cast a vote if state is not Active or if endBlock > block.number", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + + await expect( + this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof), + ).to.be.revertedWithCustomError(this.governor, "ProposalStateInvalid"); + + tx = await this.governor.connect(this.signers.bob).cancel(proposalId); + await tx.wait(); + + tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + await awaitAllDecryptionResults(); + + const newProposalId = await this.governor.latestProposalIds(this.signers.bob.address); + // 3 --> Active + expect((await this.governor.getProposalInfo(newProposalId)).state).to.equal(3); + + // Mine too many blocks so that it becomes too late to cast vote + await mineNBlocks(5); + + await expect( + this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](newProposalId, encryptedVote.handles[0], encryptedVote.inputProof), + ).to.be.revertedWithCustomError(this.governor, "ProposalStateNotActive"); + }); + + it("cannot cast a vote twice", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + // Bob receives 400k tokens and delegates to himself. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob casts a vote + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + await expect( + this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof), + ).to.be.revertedWithCustomError(this.governor, "VoterHasAlreadyVoted"); + }); + + it("proposal expires after grace period", async function () { + const targets = [this.signers.bob.address]; + const values = ["0"]; + const signatures = ["getBalanceOf(address)"]; + const calldatas = [ethers.AbiCoder.defaultAbiCoder().encode(["address"], [this.signers.bob.address])]; + const description = "description"; + const transferAmount = await this.governor.QUORUM_VOTES(); + + // Bob receives 400k tokens and delegates to himself. + await transferTokensAndDelegate( + this.signers, + this.instances, + transferAmount, + "bob", + "bob", + this.comp, + this.compAddress, + ); + + // INITIATE A PROPOSAL + let tx = await this.governor.connect(this.signers.bob).propose(targets, values, signatures, calldatas, description); + await tx.wait(); + + // DECRYPTION FOR THE TOKEN THRESHOLD + await awaitAllDecryptionResults(); + const proposalId = await this.governor.latestProposalIds(this.signers.bob.address); + + // VOTE + // Bob casts a vote + let input = this.instances.bob.createEncryptedInput(this.governorAddress, this.signers.bob.address); + input.addBool(true); + let encryptedVote = await input.encrypt(); + tx = await this.governor + .connect(this.signers.bob) + ["castVote(uint256,bytes32,bytes)"](proposalId, encryptedVote.handles[0], encryptedVote.inputProof); + await tx.wait(); + + // Mine blocks + await mineNBlocks(4); + + // REQUEST DECRYPTION + tx = await this.governor.requestVoteDecryption(proposalId); + await tx.wait(); + + // POST-DECRYPTION RESULTS + await awaitAllDecryptionResults(); + + // Proposal is queued + tx = await this.governor.queue(proposalId); + await tx.wait(); + + let proposalInfo = await this.governor.getProposalInfo(proposalId); + const eta = proposalInfo.eta; + const deadlineExecutionTransaction = eta + (await this.timelock.GRACE_PERIOD()); + + await ethers.provider.send("evm_setNextBlockTimestamp", [deadlineExecutionTransaction.toString()]); + await mineNBlocks(1); + + await expect(this.governor.execute(proposalId)).to.be.revertedWith( + "Timelock::executeTransaction: Transaction is stale.", + ); + + proposalInfo = await this.governor.getProposalInfo(proposalId); + // 9 ==> Expired + expect(proposalInfo.state).to.equal(9); + }); +}); diff --git a/test/handleTypeCheck.ts b/test/handleTypeCheck.ts new file mode 100644 index 0000000..dfe7ddc --- /dev/null +++ b/test/handleTypeCheck.ts @@ -0,0 +1,28 @@ +export const EBOOL_T = 0; +export const EUINT4_T = 1; +export const EUINT8_T = 2; +export const EUINT16_T = 3; +export const EUINT32_T = 4; +export const EUINT64_T = 5; +export const EUINT128_T = 6; +export const EUINT160_T = 7; // @dev It is the one for eaddresses. +export const EUINT256_T = 8; +export const EBYTES64_T = 9; +export const EBYTES128_T = 10; +export const EBYTES256_T = 11; + +export function verifyType(handle: bigint, expectedType: number) { + if (handle === 0n) { + throw "Handle is not initialized"; + } + + if (handle.toString(2).length > 256) { + throw "Handle is not a bytes32"; + } + + const typeCt = handle >> 8n; + + if (Number(typeCt % 256n) !== expectedType) { + throw "Wrong encrypted type for the handle"; + } +} diff --git a/test/instance.ts b/test/instance.ts index 36f27ba..0f687a0 100644 --- a/test/instance.ts +++ b/test/instance.ts @@ -1,87 +1,350 @@ -import { toBufferBE } from "bigint-buffer"; -import { Signer } from "ethers"; -import fhevmjs, { FhevmInstance, getPublicKeyCallParams } from "fhevmjs"; -import { ethers as hethers } from "hardhat"; +import dotenv from "dotenv"; +import { + clientKeyDecryptor, + createEIP712, + createInstance as createFhevmInstance, + generateKeypair, + getCiphertextCallParams, +} from "fhevmjs"; +import { readFileSync } from "fs"; +import * as fs from "fs"; +import { ethers, ethers as hethers, network } from "hardhat"; +import { homedir } from "os"; +import path from "path"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; +import { createEncryptedInputMocked, reencryptRequestMocked } from "./fhevmjsMocked"; +import { + EBOOL_T, + EBYTES64_T, + EBYTES128_T, + EBYTES256_T, + EUINT4_T, + EUINT8_T, + EUINT16_T, + EUINT32_T, + EUINT64_T, + EUINT128_T, + EUINT160_T, + EUINT256_T, + verifyType, +} from "./handleTypeCheck"; import type { Signers } from "./signers"; import { FhevmInstances } from "./types"; -const HARDHAT_NETWORK = process.env.HARDHAT_NETWORK; +const FHE_CLIENT_KEY_PATH = process.env.FHE_CLIENT_KEY_PATH; -let publicKey: string | undefined; -let chainId: number; +let clientKey: Uint8Array | undefined; -export const createInstances = async ( - contractAddress: string, - ethers: typeof hethers, - accounts: Signers, -): Promise => { +const kmsAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.kmsverifier"), +).KMS_VERIFIER_CONTRACT_ADDRESS; + +const aclAdd = dotenv.parse( + fs.readFileSync("node_modules/fhevm-core-contracts/addresses/.env.acl"), +).ACL_CONTRACT_ADDRESS; + +const createInstanceMocked = async () => { + const instance = { + reencrypt: reencryptRequestMocked, + createEncryptedInput: createEncryptedInputMocked, + getPublicKey: () => "0xFFAA44433", + generateKeypair: generateKeypair, + createEIP712: createEIP712(network.config.chainId), + }; + + return instance; +}; + +export const createInstances = async (accounts: Signers): Promise => { // Create instance const instances: FhevmInstances = {} as FhevmInstances; - await Promise.all( - Object.keys(accounts).map(async (k) => { - instances[k as keyof FhevmInstances] = await createInstance( - contractAddress, - accounts[k as keyof Signers], - ethers, - ); - }), - ); - + if (network.name === "hardhat") { + await Promise.all( + Object.keys(accounts).map(async (k) => { + instances[k as keyof FhevmInstances] = await createInstanceMocked(); + }), + ); + } else { + await Promise.all( + Object.keys(accounts).map(async (k) => { + instances[k as keyof FhevmInstances] = await createInstance(); + }), + ); + } return instances; }; -export const createInstance = async (contractAddress: string, account: Signer, ethers: typeof hethers) => { - // 1. Get chain id - const provider = ethers.provider; +export const createInstance = async () => { + const instance = await createFhevmInstance({ + networkUrl: network.config.url, + kmsContractAddress: kmsAdd, + aclContractAddress: aclAdd, + gatewayUrl: "http://localhost:7077", + }); + return instance; +}; + +const getCiphertext = async (handle: bigint, ethers: typeof hethers): Promise => { + return ethers.provider.call(getCiphertextCallParams(handle)); +}; - const network = await provider.getNetwork(); - chainId = +network.chainId.toString(); // Need to be a number - try { - // Get blockchain public key - const ret = await provider.call(getPublicKeyCallParams()); - const decoded = ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], ret); - publicKey = decoded[0]; - } catch (e) { - publicKey = undefined; +const getDecryptor = () => { + if (clientKey == null) { + if (FHE_CLIENT_KEY_PATH) { + clientKey = readFileSync(FHE_CLIENT_KEY_PATH); + } else { + const home = homedir(); + const clientKeyPath = path.join(home, "network-fhe-keys/cks"); + clientKey = readFileSync(clientKeyPath); + } } + return clientKeyDecryptor(clientKey); +}; - const instance = await fhevmjs.createInstance({ chainId, publicKey }); - - if (HARDHAT_NETWORK === "hardhat") { - instance.encryptBool = createUintToUint8ArrayFunction(1); - instance.encrypt4 = createUintToUint8ArrayFunction(4); - instance.encrypt8 = createUintToUint8ArrayFunction(8); - instance.encrypt16 = createUintToUint8ArrayFunction(16); - instance.encrypt32 = createUintToUint8ArrayFunction(32); - instance.encrypt64 = createUintToUint8ArrayFunction(64); - instance.encryptAddress = createUintToUint8ArrayFunction(160); - instance.decrypt = (_, hexadecimalString) => BigInt(hexadecimalString); - instance.decryptAddress = (_, hexadecimalString) => ethers.getAddress(hexadecimalString.slice(26, 66)); +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bool} + */ +export const decryptBool = async (handle: bigint): Promise => { + verifyType(handle, EBOOL_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return (await getClearText(handle)) === "1"; + } else { + return getDecryptor().decryptBool(await getCiphertext(handle, ethers)); } - await generatePublicKey(contractAddress, account, instance); +}; - return instance; +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decrypt4 = async (handle: bigint): Promise => { + verifyType(handle, EUINT4_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt4(await getCiphertext(handle, ethers)); + } }; -const generatePublicKey = async (contractAddress: string, signer: Signer, instance: FhevmInstance) => { - // Generate token to decrypt - const generatedToken = instance.generatePublicKey({ - verifyingContract: contractAddress, - }); - // Sign the public key - const signature = await signer.signTypedData( - generatedToken.eip712.domain, - { Reencrypt: generatedToken.eip712.types.Reencrypt }, // Need to remove EIP712Domain from types - generatedToken.eip712.message, - ); - instance.setSignature(contractAddress, signature); -}; - -function createUintToUint8ArrayFunction(numBits: number) { - const numBytes = Math.ceil(numBits / 8); - return function (uint: number | bigint | boolean) { - const buffer = toBufferBE(BigInt(uint), numBytes); - return buffer; - }; -} +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bigint} + */ +export const decrypt8 = async (handle: bigint): Promise => { + verifyType(handle, EUINT8_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt8(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decrypt16 = async (handle: bigint): Promise => { + verifyType(handle, EUINT16_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt16(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decrypt32 = async (handle: bigint): Promise => { + verifyType(handle, EUINT32_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt32(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decrypt64 = async (handle: bigint): Promise => { + verifyType(handle, EUINT64_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt64(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + +export const decrypt128 = async (handle: bigint): Promise => { + verifyType(handle, EUINT128_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt128(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + +export const decrypt256 = async (handle: bigint): Promise => { + verifyType(handle, EUINT256_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decrypt256(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {string} + */ +export const decryptAddress = async (handle: bigint): Promise => { + verifyType(handle, EUINT160_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + const bigintAdd = BigInt(await getClearText(handle)); + const handleStr = "0x" + bigintAdd.toString(16).padStart(40, "0"); + return handleStr; + } else { + return getDecryptor().decryptAddress(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bigint} + */ + +export const decryptEbytes64 = async (handle: bigint): Promise => { + verifyType(handle, EBYTES64_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decryptEbytes64(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decryptEbytes128 = async (handle: bigint): Promise => { + verifyType(handle, EBYTES128_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decryptEbytes128(await getCiphertext(handle, ethers)); + } +}; + +/** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ +export const decryptEbytes256 = async (handle: bigint): Promise => { + verifyType(handle, EBYTES256_T); + + if (network.name === "hardhat") { + await awaitCoprocessor(); + + return BigInt(await getClearText(handle)); + } else { + return getDecryptor().decryptEbytes256(await getCiphertext(handle, ethers)); + } +}; diff --git a/test/operatorsPrices.json b/test/operatorsPrices.json new file mode 100644 index 0000000..8c861dc --- /dev/null +++ b/test/operatorsPrices.json @@ -0,0 +1,530 @@ +{ + "fheAdd": { + "binary": true, + "scalar": { + "1": 65000, + "2": 94000, + "3": 133000, + "4": 162000, + "5": 188000, + "6": 218000, + "8": 253000 + }, + "nonScalar": { + "1": 65000, + "2": 94000, + "3": 133000, + "4": 162000, + "5": 188000, + "6": 218000, + "8": 253000 + } + }, + "fheSub": { + "binary": true, + "scalar": { + "1": 65000, + "2": 94000, + "3": 133000, + "4": 162000, + "5": 188000, + "6": 218000, + "8": 253000 + }, + "nonScalar": { + "1": 65000, + "2": 94000, + "3": 133000, + "4": 162000, + "5": 188000, + "6": 218000, + "8": 253000 + } + }, + "fheMul": { + "binary": true, + "scalar": { + "1": 88000, + "2": 159000, + "3": 208000, + "4": 264000, + "5": 356000, + "6": 480000, + "8": 647000 + }, + "nonScalar": { + "1": 150000, + "2": 197000, + "3": 262000, + "4": 359000, + "5": 641000, + "6": 1145000, + "8": 2045000 + } + }, + "fheDiv": { + "binary": true, + "scalar": { + "1": 139000, + "2": 238000, + "3": 314000, + "4": 398000, + "5": 584000, + "6": 857000, + "8": 1258000 + } + }, + "fheRem": { + "binary": true, + "scalar": { + "1": 286000, + "2": 460000, + "3": 622000, + "4": 805000, + "5": 1095000, + "6": 1499000, + "8": 2052000 + } + }, + "fheBitAnd": { + "binary": true, + "scalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + } + }, + "fheBitOr": { + "binary": true, + "scalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + } + }, + "fheBitXor": { + "binary": true, + "scalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "0": 26000, + "1": 32000, + "2": 34000, + "3": 34000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + } + }, + "fheShl": { + "binary": true, + "scalar": { + "1": 35000, + "2": 35000, + "3": 35000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "1": 116000, + "2": 133000, + "3": 153000, + "4": 183000, + "5": 227000, + "6": 282000, + "8": 350000 + } + }, + "fheShr": { + "binary": true, + "scalar": { + "1": 35000, + "2": 35000, + "3": 35000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "1": 116000, + "2": 133000, + "3": 153000, + "4": 183000, + "5": 227000, + "6": 282000, + "8": 350000 + } + }, + "fheRotl": { + "binary": true, + "scalar": { + "1": 35000, + "2": 35000, + "3": 35000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "1": 116000, + "2": 133000, + "3": 153000, + "4": 183000, + "5": 227000, + "6": 282000, + "8": 350000 + } + }, + "fheRotr": { + "binary": true, + "scalar": { + "1": 35000, + "2": 35000, + "3": 35000, + "4": 35000, + "5": 38000, + "6": 41000, + "8": 44000 + }, + "nonScalar": { + "1": 116000, + "2": 133000, + "3": 153000, + "4": 183000, + "5": 227000, + "6": 282000, + "8": 350000 + } + }, + "fheEq": { + "binary": true, + "scalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + }, + "nonScalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheNe": { + "binary": true, + "scalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + }, + "nonScalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheGe": { + "binary": true, + "scalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + }, + "nonScalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + } + }, + "fheGt": { + "binary": true, + "scalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + }, + "nonScalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + } + }, + "fheLe": { + "binary": true, + "scalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + }, + "nonScalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + } + }, + "fheLt": { + "binary": true, + "scalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + }, + "nonScalar": { + "1": 70000, + "2": 82000, + "3": 105000, + "4": 128000, + "5": 156000, + "6": 190000, + "8": 231000 + } + }, + "fheMin": { + "binary": true, + "scalar": { + "1": 121000, + "2": 128000, + "3": 150000, + "4": 164000, + "5": 192000, + "6": 225000, + "8": 264000 + }, + "nonScalar": { + "1": 121000, + "2": 128000, + "3": 153000, + "4": 183000, + "5": 210000, + "6": 241000, + "8": 277000 + } + }, + "fheMax": { + "binary": true, + "scalar": { + "1": 121000, + "2": 128000, + "3": 150000, + "4": 164000, + "5": 192000, + "6": 225000, + "8": 264000 + }, + "nonScalar": { + "1": 121000, + "2": 128000, + "3": 153000, + "4": 183000, + "5": 210000, + "6": 241000, + "8": 277000 + } + }, + "fheNeg": { + "binary": false, + "types": { + "1": 60000, + "2": 95000, + "3": 131000, + "4": 160000, + "5": 199000, + "6": 248000, + "8": 309000 + } + }, + "fheNot": { + "binary": false, + "types": { + "0": 30000, + "1": 33000, + "2": 34000, + "3": 35000, + "4": 36000, + "5": 37000, + "6": 38000, + "8": 39000 + } + }, + "cast": { + "binary": false, + "types": { + "0": 200, + "1": 200, + "2": 200, + "3": 200, + "4": 200, + "5": 200, + "6": 200, + "8": 200 + } + }, + "trivialEncrypt": { + "binary": false, + "types": { + "0": 100, + "1": 100, + "2": 100, + "3": 200, + "4": 300, + "5": 600, + "6": 650, + "7": 700, + "8": 800, + "9": 1600, + "10": 3200, + "11": 6400 + } + }, + "ifThenElse": { + "binary": false, + "types": { + "0": 43000, + "1": 45000, + "2": 47000, + "3": 47000, + "4": 50000, + "5": 53000, + "6": 70000, + "7": 80000, + "8": 90000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheRand": { + "binary": false, + "types": { + "0": 100000, + "1": 100000, + "2": 100000, + "3": 100000, + "4": 100000, + "5": 100000, + "6": 100000, + "8": 100000, + "9": 200000, + "10": 300000, + "11": 400000 + } + }, + "fheRandBounded": { + "binary": false, + "types": { + "1": 100000, + "2": 100000, + "3": 100000, + "4": 100000, + "5": 100000, + "6": 100000, + "8": 100000 + } + } +} diff --git a/test/oracleDecrypt/testAsyncDecrypt.ts b/test/oracleDecrypt/testAsyncDecrypt.ts deleted file mode 100644 index 9eb7435..0000000 --- a/test/oracleDecrypt/testAsyncDecrypt.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { expect } from "chai"; -import { ethers, network } from "hardhat"; - -import { asyncDecrypt, awaitAllDecryptionResults } from "../asyncDecrypt"; -import { getSigners, initSigners } from "../signers"; - -describe("TestAsyncDecrypt", function () { - before(async function () { - await asyncDecrypt(); - await initSigners(3); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const contractFactory = await ethers.getContractFactory("TestAsyncDecrypt"); - this.contract = await contractFactory.connect(this.signers.alice).deploy(); - }); - - it("test async decrypt bool would fail if maxTimestamp is above 1 day", async function () { - if (network.name === "hardhat") { - // mocked mode - await expect(this.contract.connect(this.signers.carol).requestBoolAboveDelay()).to.be.revertedWith( - "maxTimestamp exceeded MAX_DELAY", - ); - } else { - // fhevm-mode - const tx = await this.contract.connect(this.signers.carol).requestBoolAboveDelay({ gasLimit: 1_000_000 }); - await expect(tx.wait()).to.throw; - } - }); - - it("test async decrypt bool", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestBool({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBool(); - expect(y).to.equal(true); - }); - - it("test async decrypt FAKE bool", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeBool.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt uint4", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint4({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint4(); - expect(y).to.equal(4); - }); - - it("test async decrypt FAKE uint4", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeUint4.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt uint8", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint8({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint8(); - expect(y).to.equal(42); - }); - - it("test async decrypt FAKE uint8", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeUint8.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt uint16", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint16({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint16(); - expect(y).to.equal(16); - }); - - it("test async decrypt FAKE uint16", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeUint16.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt uint32", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint32(5, 15, { gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint32(); - expect(y).to.equal(52); // 5+15+32 - }); - - it("test async decrypt FAKE uint32", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeUint32.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt uint64", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint64({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint64(); - expect(y).to.equal(64); - }); - - it("test async decrypt FAKE uint64", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeUint64.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); - - it("test async decrypt address", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestAddress({ gasLimit: 500_000 }); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yAddress(); - expect(y).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - }); - - it("test async decrypt FAKE address", async function () { - if (network.name !== "hardhat") { - // only in fhevm mode - const txObject = await this.contract - .connect(this.signers.carol) - .requestFakeAddress.populateTransaction({ gasLimit: 5_000_000 }); - const tx = await this.signers.carol.sendTransaction(txObject); - let receipt = null; - let waitTime = 0; - while (receipt === null && waitTime < 15000) { - receipt = await ethers.provider.getTransactionReceipt(tx.hash); - if (receipt === null) { - console.log("Trying again to fetch txn receipt...."); - await new Promise((resolve) => setTimeout(resolve, 5000)); // Wait for 5 seconds - waitTime += 5000; - } - } - expect(waitTime >= 15000).to.be.true; - } - }); -}); diff --git a/test/reencrypt.ts b/test/reencrypt.ts new file mode 100644 index 0000000..8c79e63 --- /dev/null +++ b/test/reencrypt.ts @@ -0,0 +1,196 @@ +import { Signers } from "./signers"; +import type { FhevmInstances } from "./types"; + +const EBOOL_T = 0; +const EUINT4_T = 1; +const EUINT8_T = 2; +const EUINT16_T = 3; +const EUINT32_T = 4; +const EUINT64_T = 5; +const EUINT128_T = 6; +const EUINT160_T = 7; // @dev It is the one for eaddresses. +const EUINT256_T = 8; +const EBYTES64_T = 9; +const EBYTES128_T = 10; +const EBYTES256_T = 11; + +export function verifyType(handle: bigint, expectedType: number) { + if (handle === 0n) { + throw "Handle is not initialized"; + } + + if (handle.toString(2).length > 256) { + throw "Handle is not a bytes32"; + } + + const typeCt = handle >> 8n; + + if (Number(typeCt % 256n) !== expectedType) { + throw "Wrong encrypted type for the handle"; + } +} + +export async function reencryptEbool( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBOOL_T); + return (await reencryptHandle(signers, instances, user, handle, contractAddress)) === 1n; +} + +export async function reencryptEuint4( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT4_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEuint8( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT8_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEuint16( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT16_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEuint32( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT32_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEuint64( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT64_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEuint128( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT128_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEaddress( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT160_T); + const addressAsUint160: bigint = await reencryptHandle(signers, instances, user, handle, contractAddress); + const handleStr = "0x" + addressAsUint160.toString(16).padStart(40, "0"); + return handleStr; +} + +export async function reencryptEuint256( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT256_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEbytes64( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES64_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEbytes128( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES128_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +export async function reencryptEbytes256( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES256_T); + return reencryptHandle(signers, instances, user, handle, contractAddress); +} + +/** + * @dev This function is to reencrypt handles. + * It does not verify types. + */ +async function reencryptHandle( + signers: Signers, + instances: FhevmInstances, + user: string, + handle: bigint, + contractAddress: string, +): Promise { + const { publicKey: publicKey, privateKey: privateKey } = instances[user as keyof FhevmInstances].generateKeypair(); + const eip712 = instances[user as keyof FhevmInstances].createEIP712(publicKey, contractAddress); + const signature = await signers[user as keyof Signers].signTypedData( + eip712.domain, + { Reencrypt: eip712.types.Reencrypt }, + eip712.message, + ); + + const reencryptedHandle = await instances[user as keyof FhevmInstances].reencrypt( + handle, + privateKey, + publicKey, + signature.replace("0x", ""), + contractAddress, + signers[user as keyof Signers].address, + ); + + return reencryptedHandle; +} diff --git a/test/signers.ts b/test/signers.ts index 4715592..8b017d1 100644 --- a/test/signers.ts +++ b/test/signers.ts @@ -1,5 +1,11 @@ import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; -import { ethers } from "hardhat"; +import { exec as oldExec } from "child_process"; +import { config, ethers } from "hardhat"; +import { promisify } from "util"; + +import { waitForBalance } from "./utils"; + +const exec = promisify(oldExec); export interface Signers { alice: HardhatEthersSigner; @@ -11,19 +17,59 @@ export interface Signers { let signers: Signers; -export const initSigners = async (): Promise => { +const keys: (keyof Signers)[] = ["alice", "bob", "carol", "dave", "eve"]; + +const getCoin = async (address: string) => { + const containerName = process.env["TEST_CONTAINER_NAME"] || "zama-dev-fhevm-validator-1"; + const response = await exec(`docker exec -i ${containerName} faucet ${address} | grep height`); + const res = JSON.parse(response.stdout); + if (res.raw_log.match("account sequence mismatch")) await getCoin(address); +}; + +const faucet = async (address: string) => { + const balance = await ethers.provider.getBalance(address); + if (balance > 0) return; + await getCoin(address); + await waitForBalance(address); +}; + +export const initSigners = async (quantity: number): Promise => { + const q = process.env.HARDHAT_PARALLEL ? Math.min(quantity, 5) : 5; if (!signers) { - const eSigners = await ethers.getSigners(); - signers = { - alice: eSigners[0], - bob: eSigners[1], - carol: eSigners[2], - dave: eSigners[3], - eve: eSigners[4], - }; + if (process.env.HARDHAT_PARALLEL && config.defaultNetwork === "local") { + signers = { + alice: ethers.Wallet.createRandom().connect(ethers.provider), + bob: ethers.Wallet.createRandom().connect(ethers.provider), + carol: ethers.Wallet.createRandom().connect(ethers.provider), + dave: ethers.Wallet.createRandom().connect(ethers.provider), + eve: ethers.Wallet.createRandom().connect(ethers.provider), + }; + } else if (!process.env.HARDHAT_PARALLEL) { + const eSigners = await ethers.getSigners(); + signers = { + alice: eSigners[0], + bob: eSigners[1], + carol: eSigners[2], + dave: eSigners[3], + eve: eSigners[4], + }; + } else { + throw new Error("Can't run parallel mode if network is not 'local'"); + } + + if (config.defaultNetwork === "local") { + const faucetP: Promise[] = []; + for (let i = 0; i < q; i += 1) { + const account = signers[keys[i]]; + faucetP.push(faucet(account.address)); + } + await Promise.all(faucetP); + } } }; export const getSigners = async (): Promise => { return signers; }; + +export const requestFaucet = faucet; diff --git a/test/types.ts b/test/types.ts index 1e13854..6afcffe 100644 --- a/test/types.ts +++ b/test/types.ts @@ -1,5 +1,15 @@ import type { FhevmInstance } from "fhevmjs"; +import type { Signers } from "./signers"; + +declare module "mocha" { + export interface Context { + signers: Signers; + contractAddress: string; + instances: FhevmInstances; + } +} + export interface FhevmInstances { alice: FhevmInstance; bob: FhevmInstance; diff --git a/test/utils.ts b/test/utils.ts index 0486b3d..ae071be 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,11 +1,11 @@ +import { toBufferBE } from "bigint-buffer"; import { ContractMethodArgs, Typed } from "ethers"; -import { ethers } from "hardhat"; +import { ethers, network } from "hardhat"; import { TypedContractMethod } from "../types/common"; -import { getSigners } from "./signers"; export const waitForBlock = (blockNumber: bigint | number) => { - if (process.env.HARDHAT_NETWORK === "hardhat") { + if (network.name === "hardhat") { return new Promise((resolve, reject) => { const intervalId = setInterval(async () => { try { @@ -37,7 +37,7 @@ export const waitForBlock = (blockNumber: bigint | number) => { export const waitNBlocks = async (Nblocks: number) => { const currentBlock = await ethers.provider.getBlockNumber(); - if (process.env.HARDHAT_NETWORK === "hardhat") { + if (network.name === "hardhat") { await produceDummyTransactions(Nblocks); } await waitForBlock(currentBlock + Nblocks); @@ -71,19 +71,39 @@ export const createTransaction = async { - const nullAddress = "0x0000000000000000000000000000000000000000"; - const signers = await getSigners(); - while (blockCount > 0) { - blockCount--; - // Sending 0 ETH to the null address - const tx = await signers.dave.sendTransaction({ + let counter = blockCount; + while (counter >= 0) { + counter--; + const [signer] = await ethers.getSigners(); + const nullAddress = "0x0000000000000000000000000000000000000000"; + const tx = { to: nullAddress, - value: ethers.parseEther("0"), - }); + value: 0n, + }; + const receipt = await signer.sendTransaction(tx); + await receipt.wait(); } }; export const mineNBlocks = async (n: number) => { - // this only works in mocked mode - await ethers.provider.send("hardhat_mine", ["0x" + n.toString(16)]); + for (let index = 0; index < n; index++) { + await ethers.provider.send("evm_mine"); + } +}; + +export const bigIntToBytes64 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 64)); +}; + +export const bigIntToBytes128 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 128)); +}; + +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +export const bigIntToBytes = (value: bigint) => { + const byteArrayLength = Math.ceil(value.toString(2).length / 8); + return new Uint8Array(toBufferLE(value, byteArrayLength)); }; diff --git a/tsconfig.json b/tsconfig.json index 734e21a..f5ef6d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, - "lib": ["es2020"], + "lib": ["es2020", "dom"], "module": "commonjs", "moduleResolution": "node", "noImplicitAny": true,