From 1f371a09cc10548cf21f894e99294bcd0dc34fe4 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 23 May 2024 15:41:26 +1000 Subject: [PATCH 01/62] started drafting the spec --- packages/docs/contracts.spec.md | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/docs/contracts.spec.md diff --git a/packages/docs/contracts.spec.md b/packages/docs/contracts.spec.md new file mode 100644 index 00000000..cbb776e2 --- /dev/null +++ b/packages/docs/contracts.spec.md @@ -0,0 +1,57 @@ +# Enclave Specification + +This document is a specification of the smart contract components to Enclave, an open source protocol for Encrypted Execution Environments (E3). + +## Actors + +There are five groups of actors in Enclave: + +1. **Requesters:** Anyone can request an E3 from the Enclave protocol by calling the corresponding smart contract entrypoint and depositing a bond proportional to the number, threshold, and duration of Cypher Nodes that they request. +2. **Data Providers:** Individuals and systems providing inputs to a requested E3. Data Providers contribute data encrypted to the public threshold key that is created, and published on chain, by the Cypher Nodes selected for a requested E3. +3. **Execution Modules:** Enclave is a modular framework, allowing the choice of many different Execution Modules in which to run encrypted computations. Broadly, Execution Modules fall into two categories: (1) Provable (like RISC Zero’s virtual machine[^1], Arbitrum’s WAVM[^2], or Succinct's SP1[^3]) and (2) Oracle-based. The former provides cryptographic guarantees of correct execution, while the latter provides economic guarantees of correct execution. +4. **Cypher Nodes:** Cypher Nodes are responsible for creating threshold public keys and decrypting the cyphertext output for each requested computation. Cypher Nodes can be registered by anyone staking Enclave tokens. +5. **Token Holders:** As the top-level governance body, Enclave token holders are responsible for setting protocol parameters, overseeing protocol upgrades, and facilitating dispute resolution. + +Enclave is a smart contract protocol for coordinating the interactions between these various actors. + +## Components + +Enclave is a modular architecture, this section describes each of the various smart contract components that constitute the Enclave protocol. + +### Core + +Contains the main entrypoints for requesting and publishing inputs to E3s. + +**`requestE3(uint256 computationId, bytes memory data)`** + +**`publishInput(bytes32 e3Id, bytes memory data)`** + +**`publishOutput(bytes32 e3Id, bytes memory data)`** + +**`registerNode()`** + +### CyphernodeRegistry + +Registry of staked Cyphernodes that are eligible to be selected for E3 duties. + +### ComputationRegistry + +Registry of computations which can be requested via the protocol. + +### IComputationModule + +Computation module contracts implement any specific + +### ExecutionModuleRegistry + +Registry of execution modules on which a requested computation can be run. + +### IExecutionModule + +Interface defining interactions with any given execution module. + +--- + +[^1]: RISC Zero is a general-purpose, zero-knowledge virtual machine. More information can be found on their website at https://risczero.com +[^2]: WAVM is Arbitrum’s execution environment, provable via optimistic fraud proofs. More information can be found on their website at https://arbitrum.io +[^3]: SP1 is a performant, 100% open-source, contributor-friendly zero-knowledge virtual machine (zkVM) that can prove the execution of arbitrary Rust (or any LLVM-compiled language) programs. More information can be found on Succinct's github at https://github.com/succinctlabs/sp1 From 67716cc21ef6adc52ebd613f220959630f5fce92 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 24 May 2024 16:19:33 +1000 Subject: [PATCH 02/62] started drafting Enclave.sol --- packages/evm/contracts/Enclave.sol | 83 +++++++++++++++++++ .../Interfaces/IComputationModule.sol | 8 ++ .../Interfaces/ICypherNodeRegistry.sol | 9 ++ .../evm/contracts/Interfaces/IEnclave.sol | 28 +++++++ .../contracts/Interfaces/IExecutionModule.sol | 8 ++ .../contracts/Interfaces/IInputVerifier.sol | 8 ++ 6 files changed, 144 insertions(+) create mode 100644 packages/evm/contracts/Enclave.sol create mode 100644 packages/evm/contracts/Interfaces/IComputationModule.sol create mode 100644 packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol create mode 100644 packages/evm/contracts/Interfaces/IEnclave.sol create mode 100644 packages/evm/contracts/Interfaces/IExecutionModule.sol create mode 100644 packages/evm/contracts/Interfaces/IInputVerifier.sol diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol new file mode 100644 index 00000000..dc474617 --- /dev/null +++ b/packages/evm/contracts/Enclave.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IEnclave } from "./Interfaces/IEnclave.sol"; +import { IComputationModule } from "./Interfaces/IComputationModule.sol"; +import { ICypherNodeRegistry } from "./Interfaces/ICypherNodeRegistry.sol"; +import { IExecutionModule } from "./Interfaces/IExecutionModule.sol"; +import { IInputVerifier } from "./Interfaces/IInputVerifier.sol"; + +struct E3 { + uint32[2] threshold; // M/N threshold for the committee. + uint256 expiration; // timestamp when committee duties expire. + address inputVerifier; // address of the input verifier contract. + bytes32 committeeId; // ID of the selected committee. +} + +contract Enclave is IEnclave { + ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. + uint256 public maxDuration; // TODO: add a setter function. + uint256 public nexte3Id; // ID of the next E3. + uint256 public requests; // total number of requests made to Enclave. + + mapping(address moduleAddress => bool allowed) public computationModules; // Mapping of allowed computation modules. + mapping(address moduleAddress => bool allowed) public executionModules; // Mapping of allowed execution modules. + mapping(uint256 id => E3) public e3s; // Mapping of E3s. + + event E3Requested( + uint256 e3Id, + E3 e3, + uint256 indexed poolId, + address indexed computationModule, + address indexed executionModule + ); + event InputPublished(uint256 e3Id, bytes data); + + error InputDeadlinePassed(uint e3Id, uint expiration); + error InvalidComputation(); + error InvalidExecutionModuleSetup(); + error InvalidInput(); + error InvalidDuration(); + error InvalidThreshold(); + error PaymentRequired(); + + constructor(uint256 _maxDuration) { + maxDuration = _maxDuration; + } + + function request( + uint256 poolId, + uint32[2] calldata threshold, + uint256 duration, + address computationModule, + bytes memory computationParams, + address executionModule, + bytes memory emParams + ) external payable returns (uint e3Id) { + require(msg.value > 0, PaymentRequired()); // TODO: allow for other payment methods or only native tokens? + + require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); + require(duration > 0 && duration <= maxDuration, InvalidDuration()); + + address inputVerifier = IComputationModule(computationModule).validate(computationParams); + require(inputVerifier != address(0), InvalidComputation()); + + // TODO: validate that the requested computation can be performed by the given execution module. + require(IExecutionModule(executionModule).validate(emParams), InvalidExecutionModuleSetup()); + + e3Id = nexte3Id; + bytes32 committeeId = cypherNodeRegistry.selectCommittee(poolId, threshold); + // TODO: validate that the selected pool accepts both the computation and execution modules. + e3s[e3Id] = E3(threshold, block.timestamp + duration, inputVerifier, committeeId); + + emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); + } + + function input(uint e3Id, bytes calldata data) external { + E3 storage e3 = e3s[e3Id]; + require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); + require(IInputVerifier(e3.inputVerifier).validate(msg.sender, data), InvalidInput()); + + emit InputPublished(e3Id, data); + } +} diff --git a/packages/evm/contracts/Interfaces/IComputationModule.sol b/packages/evm/contracts/Interfaces/IComputationModule.sol new file mode 100644 index 00000000..7c9e2b78 --- /dev/null +++ b/packages/evm/contracts/Interfaces/IComputationModule.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface IComputationModule { + /// @notice This function should be called by the Enclave contract to validate the computation parameters. + /// @param params ABI encoded computation parameters. + function validate(bytes calldata params) external returns (address inputVerifier); +} diff --git a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol new file mode 100644 index 00000000..825ea0cb --- /dev/null +++ b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface ICypherNodeRegistry { + /// @notice This function should be called by the Enclave contract to select a node committee. + /// @param poolId ID of the pool of nodes from which to select the committee. + /// @param threshold The M/N threshold for the committee. + function selectCommittee(uint256 poolId, uint32[2] calldata threshold) external returns (bytes32 committeeId); +} diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol new file mode 100644 index 00000000..13fd930d --- /dev/null +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface IEnclave { + /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). + /// @param poolId ID of the pool of nodes from which to select the committee. + /// @param threshold The M/N threshold for the committee. + /// @param duration The duration of the computation in seconds. + /// @param computationModule Address of the computation module. + /// @param computationParams ABI encoded computation parameters. + /// @param executionModule Address of the execution module. + /// @param emParams ABI encoded execution module parameters. + /// @return e3Id ID of the E3. + function request( + uint256 poolId, + uint32[2] calldata threshold, + uint256 duration, + address computationModule, + bytes memory computationParams, + address executionModule, + bytes memory emParams + ) external payable returns (uint e3Id); + + /// @notice This function should be called to input data into an Encrypted Execution Environment (E3). + /// @param e3Id ID of the E3. + /// @param data ABI encoded input data. + function input(uint e3Id, bytes calldata data) external; +} diff --git a/packages/evm/contracts/Interfaces/IExecutionModule.sol b/packages/evm/contracts/Interfaces/IExecutionModule.sol new file mode 100644 index 00000000..d8997678 --- /dev/null +++ b/packages/evm/contracts/Interfaces/IExecutionModule.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface IExecutionModule { + /// @notice This function should be called by the Enclave contract to validate the execution module parameters. + /// @param params ABI encoded execution module parameters. + function validate(bytes calldata params) external returns (bool success); +} diff --git a/packages/evm/contracts/Interfaces/IInputVerifier.sol b/packages/evm/contracts/Interfaces/IInputVerifier.sol new file mode 100644 index 00000000..9b629613 --- /dev/null +++ b/packages/evm/contracts/Interfaces/IInputVerifier.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface IInputVerifier { + /// @notice This function should be called by the Enclave contract to validate the input parameters. + /// @param params ABI encoded input parameters. + function validate(address sender, bytes calldata params) external returns (bool success); +} From 3db9135d8dc18cf31ce38261e326ee49f5509f7b Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 24 May 2024 16:28:11 +1000 Subject: [PATCH 03/62] delete Lock.sol --- packages/evm/contracts/Lock.sol | 36 --------------------------------- 1 file changed, 36 deletions(-) delete mode 100644 packages/evm/contracts/Lock.sol diff --git a/packages/evm/contracts/Lock.sol b/packages/evm/contracts/Lock.sol deleted file mode 100644 index c236c27b..00000000 --- a/packages/evm/contracts/Lock.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.9; - -error InvalidUnlockTime(uint256 unlockTime); -error NotOwner(address owner); -error UnlockTimeNotReached(uint256 unlockTime); - -contract Lock { - uint256 public unlockTime; - address payable public owner; - - event Withdrawal(uint256 amount, uint256 when); - - constructor(uint256 _unlockTime) payable { - if (block.timestamp >= _unlockTime) { - revert InvalidUnlockTime(_unlockTime); - } - - unlockTime = _unlockTime; - owner = payable(msg.sender); - } - - function withdraw() public { - if (block.timestamp < unlockTime) { - revert UnlockTimeNotReached(unlockTime); - } - - if (msg.sender != owner) { - revert NotOwner(owner); - } - - emit Withdrawal(address(this).balance, block.timestamp); - - owner.transfer(address(this).balance); - } -} From a0d97eb3cd3ae5a5980cf70ba7440f41641b7ab2 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 24 May 2024 21:16:57 +1000 Subject: [PATCH 04/62] fix solidlity version in hardhat config --- packages/evm/hardhat.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index 1e910162..ddefc21f 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -101,7 +101,7 @@ const config: HardhatUserConfig = { tests: "./test", }, solidity: { - version: "0.8.19", + version: "0.8.26", settings: { metadata: { // Not including the metadata hash @@ -114,6 +114,7 @@ const config: HardhatUserConfig = { enabled: true, runs: 800, }, + viaIR: true, }, }, typechain: { From 7479ba2365ecf5abb4315a7acf304efd698b7aaa Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 24 May 2024 22:03:53 +1000 Subject: [PATCH 05/62] inheritance refactor --- packages/evm/contracts/Enclave.sol | 50 ++++++++++--------- .../Interfaces/IComputationModule.sol | 4 +- packages/evm/contracts/Interfaces/IE3.sol | 15 ++++++ .../evm/contracts/Interfaces/IEnclave.sol | 10 ++-- ...IInputVerifier.sol => IInputValidator.sol} | 2 +- 5 files changed, 52 insertions(+), 29 deletions(-) create mode 100644 packages/evm/contracts/Interfaces/IE3.sol rename packages/evm/contracts/Interfaces/{IInputVerifier.sol => IInputValidator.sol} (92%) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index dc474617..afc4e243 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -1,18 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { IEnclave } from "./Interfaces/IEnclave.sol"; -import { IComputationModule } from "./Interfaces/IComputationModule.sol"; +import { IEnclave, E3, IComputationModule, IExecutionModule } from "./Interfaces/IEnclave.sol"; import { ICypherNodeRegistry } from "./Interfaces/ICypherNodeRegistry.sol"; -import { IExecutionModule } from "./Interfaces/IExecutionModule.sol"; -import { IInputVerifier } from "./Interfaces/IInputVerifier.sol"; - -struct E3 { - uint32[2] threshold; // M/N threshold for the committee. - uint256 expiration; // timestamp when committee duties expire. - address inputVerifier; // address of the input verifier contract. - bytes32 committeeId; // ID of the selected committee. -} +import { IInputValidator } from "./Interfaces/IInputValidator.sol"; contract Enclave is IEnclave { ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. @@ -28,8 +19,8 @@ contract Enclave is IEnclave { uint256 e3Id, E3 e3, uint256 indexed poolId, - address indexed computationModule, - address indexed executionModule + IComputationModule indexed computationModule, + IExecutionModule indexed executionModule ); event InputPublished(uint256 e3Id, bytes data); @@ -41,6 +32,7 @@ contract Enclave is IEnclave { error InvalidThreshold(); error PaymentRequired(); + /// @param _maxDuration The maximum duration of a computation in seconds. constructor(uint256 _maxDuration) { maxDuration = _maxDuration; } @@ -49,34 +41,46 @@ contract Enclave is IEnclave { uint256 poolId, uint32[2] calldata threshold, uint256 duration, - address computationModule, + IComputationModule computationModule, bytes memory computationParams, - address executionModule, + IExecutionModule executionModule, bytes memory emParams - ) external payable returns (uint e3Id) { + ) external payable returns (uint e3Id, E3 memory e3) { require(msg.value > 0, PaymentRequired()); // TODO: allow for other payment methods or only native tokens? require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); require(duration > 0 && duration <= maxDuration, InvalidDuration()); - address inputVerifier = IComputationModule(computationModule).validate(computationParams); - require(inputVerifier != address(0), InvalidComputation()); + e3Id = nexte3Id; + nexte3Id++; + + IInputValidator inputValidator = computationModule.validate(computationParams); + require(address(inputValidator) != address(0), InvalidComputation()); // TODO: validate that the requested computation can be performed by the given execution module. - require(IExecutionModule(executionModule).validate(emParams), InvalidExecutionModuleSetup()); + require(executionModule.validate(emParams), InvalidExecutionModuleSetup()); - e3Id = nexte3Id; bytes32 committeeId = cypherNodeRegistry.selectCommittee(poolId, threshold); // TODO: validate that the selected pool accepts both the computation and execution modules. - e3s[e3Id] = E3(threshold, block.timestamp + duration, inputVerifier, committeeId); + + e3 = E3({ + threshold: threshold, + expiration: block.timestamp + duration, + computationModule: computationModule, + executionModule: executionModule, + inputValidator: inputValidator, + committeeId: committeeId + }); + e3s[e3Id] = e3; emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); } - function input(uint e3Id, bytes calldata data) external { + function input(uint e3Id, bytes calldata data) external returns (bool success) { E3 storage e3 = e3s[e3Id]; require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); - require(IInputVerifier(e3.inputVerifier).validate(msg.sender, data), InvalidInput()); + success = e3.inputValidator.validate(msg.sender, data); + require(success, InvalidInput()); emit InputPublished(e3Id, data); } diff --git a/packages/evm/contracts/Interfaces/IComputationModule.sol b/packages/evm/contracts/Interfaces/IComputationModule.sol index 7c9e2b78..55ea6e2a 100644 --- a/packages/evm/contracts/Interfaces/IComputationModule.sol +++ b/packages/evm/contracts/Interfaces/IComputationModule.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; +import { IInputValidator } from "./IInputValidator.sol"; + interface IComputationModule { /// @notice This function should be called by the Enclave contract to validate the computation parameters. /// @param params ABI encoded computation parameters. - function validate(bytes calldata params) external returns (address inputVerifier); + function validate(bytes calldata params) external returns (IInputValidator inputValidator); } diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/Interfaces/IE3.sol new file mode 100644 index 00000000..357c4d77 --- /dev/null +++ b/packages/evm/contracts/Interfaces/IE3.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IInputValidator } from ".//IInputValidator.sol"; +import { IExecutionModule } from "./IExecutionModule.sol"; +import { IComputationModule } from "./IComputationModule.sol"; + +struct E3 { + uint32[2] threshold; // M/N threshold for the committee. + uint256 expiration; // timestamp when committee duties expire. + IComputationModule computationModule; // address of the computation module contract. + IExecutionModule executionModule; // address of the execution module contract. + IInputValidator inputValidator; // address of the input verifier contract. + bytes32 committeeId; // ID of the selected committee. +} diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index 13fd930d..ca395a16 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; +import { E3, IComputationModule, IExecutionModule } from "./IE3.sol"; + interface IEnclave { /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @param poolId ID of the pool of nodes from which to select the committee. @@ -15,14 +17,14 @@ interface IEnclave { uint256 poolId, uint32[2] calldata threshold, uint256 duration, - address computationModule, + IComputationModule computationModule, bytes memory computationParams, - address executionModule, + IExecutionModule executionModule, bytes memory emParams - ) external payable returns (uint e3Id); + ) external payable returns (uint256 e3Id, E3 memory e3); /// @notice This function should be called to input data into an Encrypted Execution Environment (E3). /// @param e3Id ID of the E3. /// @param data ABI encoded input data. - function input(uint e3Id, bytes calldata data) external; + function input(uint e3Id, bytes calldata data) external returns (bool success); } diff --git a/packages/evm/contracts/Interfaces/IInputVerifier.sol b/packages/evm/contracts/Interfaces/IInputValidator.sol similarity index 92% rename from packages/evm/contracts/Interfaces/IInputVerifier.sol rename to packages/evm/contracts/Interfaces/IInputValidator.sol index 9b629613..a54c3afb 100644 --- a/packages/evm/contracts/Interfaces/IInputVerifier.sol +++ b/packages/evm/contracts/Interfaces/IInputValidator.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -interface IInputVerifier { +interface IInputValidator { /// @notice This function should be called by the Enclave contract to validate the input parameters. /// @param params ABI encoded input parameters. function validate(address sender, bytes calldata params) external returns (bool success); From ee4087e04aac956e998cb76cfac5dee4c25cdf81 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 24 May 2024 23:18:10 +1000 Subject: [PATCH 06/62] add publish and decrypt --- packages/evm/contracts/Enclave.sol | 50 ++++++++++++++++--- .../Interfaces/IComputationModule.sol | 8 +++ .../Interfaces/ICypherNodeRegistry.sol | 1 + packages/evm/contracts/Interfaces/IE3.sol | 6 ++- .../evm/contracts/Interfaces/IEnclave.sol | 20 ++++++-- .../contracts/Interfaces/IExecutionModule.sol | 4 +- .../contracts/Interfaces/IInputValidator.sol | 4 +- .../contracts/Interfaces/IOutputVerifier.sol | 10 ++++ 8 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 packages/evm/contracts/Interfaces/IOutputVerifier.sol diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index afc4e243..0f2d43f2 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.26; import { IEnclave, E3, IComputationModule, IExecutionModule } from "./Interfaces/IEnclave.sol"; import { ICypherNodeRegistry } from "./Interfaces/ICypherNodeRegistry.sol"; import { IInputValidator } from "./Interfaces/IInputValidator.sol"; +import { IOutputVerifier } from "./Interfaces/IOutputVerifier.sol"; contract Enclave is IEnclave { ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. @@ -15,6 +16,7 @@ contract Enclave is IEnclave { mapping(address moduleAddress => bool allowed) public executionModules; // Mapping of allowed execution modules. mapping(uint256 id => E3) public e3s; // Mapping of E3s. + event CiphertextOutputPublished(uint256 e3Id, bytes ciphertextOutput); event E3Requested( uint256 e3Id, E3 e3, @@ -23,14 +25,20 @@ contract Enclave is IEnclave { IExecutionModule indexed executionModule ); event InputPublished(uint256 e3Id, bytes data); + event PlaintextOutputPublished(uint256 e3Id, bytes plaintextOutput); - error InputDeadlinePassed(uint e3Id, uint expiration); + error InputDeadlinePassed(uint256 e3Id, uint256 expiration); + error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); error InvalidExecutionModuleSetup(); error InvalidInput(); error InvalidDuration(); + error InvalidOutput(); error InvalidThreshold(); + error CiphertextOutputAlreadyPublished(uint256 e3Id); + error CiphertextOutputNotPublished(uint256 e3Id); error PaymentRequired(); + error PlaintextOutputAlreadyPublished(uint256 e3Id); /// @param _maxDuration The maximum duration of a computation in seconds. constructor(uint256 _maxDuration) { @@ -45,7 +53,7 @@ contract Enclave is IEnclave { bytes memory computationParams, IExecutionModule executionModule, bytes memory emParams - ) external payable returns (uint e3Id, E3 memory e3) { + ) external payable returns (uint256 e3Id, E3 memory e3) { require(msg.value > 0, PaymentRequired()); // TODO: allow for other payment methods or only native tokens? require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); @@ -58,7 +66,8 @@ contract Enclave is IEnclave { require(address(inputValidator) != address(0), InvalidComputation()); // TODO: validate that the requested computation can be performed by the given execution module. - require(executionModule.validate(emParams), InvalidExecutionModuleSetup()); + IOutputVerifier outputVerifier = executionModule.validate(emParams); + require(address(outputVerifier) != address(0), InvalidExecutionModuleSetup()); bytes32 committeeId = cypherNodeRegistry.selectCommittee(poolId, threshold); // TODO: validate that the selected pool accepts both the computation and execution modules. @@ -69,19 +78,46 @@ contract Enclave is IEnclave { computationModule: computationModule, executionModule: executionModule, inputValidator: inputValidator, - committeeId: committeeId + outputVerifier: outputVerifier, + committeeId: committeeId, + ciphertextOutput: new bytes(0), + plaintextOutput: new bytes(0) }); e3s[e3Id] = e3; emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); } - function input(uint e3Id, bytes calldata data) external returns (bool success) { + function publishInput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 storage e3 = e3s[e3Id]; require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); - success = e3.inputValidator.validate(msg.sender, data); + bytes memory input; + (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - emit InputPublished(e3Id, data); + emit InputPublished(e3Id, input); + } + + function publishOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + E3 storage e3 = e3s[e3Id]; + require(e3.expiration <= block.timestamp, InputDeadlineNotPassed(e3Id, e3.expiration)); + require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); + bytes memory output; + (output, success) = e3.outputVerifier.verify(e3Id, data); + require(success, InvalidOutput()); + e3.ciphertextOutput = output; + + emit CiphertextOutputPublished(e3Id, output); + } + + function decryptOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + E3 storage e3 = e3s[e3Id]; + require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); + require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); + bytes memory output; + (output, success) = e3.computationModule.verify(e3Id, data); + e3.plaintextOutput = output; + + emit PlaintextOutputPublished(e3Id, output); } } diff --git a/packages/evm/contracts/Interfaces/IComputationModule.sol b/packages/evm/contracts/Interfaces/IComputationModule.sol index 55ea6e2a..89d78842 100644 --- a/packages/evm/contracts/Interfaces/IComputationModule.sol +++ b/packages/evm/contracts/Interfaces/IComputationModule.sol @@ -6,5 +6,13 @@ import { IInputValidator } from "./IInputValidator.sol"; interface IComputationModule { /// @notice This function should be called by the Enclave contract to validate the computation parameters. /// @param params ABI encoded computation parameters. + /// @return inputValidator The input validator to be used for the computation. function validate(bytes calldata params) external returns (IInputValidator inputValidator); + + /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3. + /// @param e3Id ID of the E3. + /// @param outputData ABI encoded output data to be verified. + /// @return output The output data to be published. + /// @return success Whether the output data is valid. + function verify(uint256 e3Id, bytes memory outputData) external returns (bytes memory output, bool success); } diff --git a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol index 825ea0cb..43167eb4 100644 --- a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol +++ b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol @@ -5,5 +5,6 @@ interface ICypherNodeRegistry { /// @notice This function should be called by the Enclave contract to select a node committee. /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. + /// @return committeeId ID of the selected committee. function selectCommittee(uint256 poolId, uint32[2] calldata threshold) external returns (bytes32 committeeId); } diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/Interfaces/IE3.sol index 357c4d77..2a311314 100644 --- a/packages/evm/contracts/Interfaces/IE3.sol +++ b/packages/evm/contracts/Interfaces/IE3.sol @@ -4,12 +4,16 @@ pragma solidity >=0.8.26; import { IInputValidator } from ".//IInputValidator.sol"; import { IExecutionModule } from "./IExecutionModule.sol"; import { IComputationModule } from "./IComputationModule.sol"; +import { IOutputVerifier } from "./IOutputVerifier.sol"; struct E3 { uint32[2] threshold; // M/N threshold for the committee. uint256 expiration; // timestamp when committee duties expire. IComputationModule computationModule; // address of the computation module contract. IExecutionModule executionModule; // address of the execution module contract. - IInputValidator inputValidator; // address of the input verifier contract. + IInputValidator inputValidator; // address of the input validator contract. + IOutputVerifier outputVerifier; // address of the output verifier contract. bytes32 committeeId; // ID of the selected committee. + bytes ciphertextOutput; // encrypted output data. + bytes plaintextOutput; // decrypted output data. } diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index ca395a16..99172428 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -13,6 +13,7 @@ interface IEnclave { /// @param executionModule Address of the execution module. /// @param emParams ABI encoded execution module parameters. /// @return e3Id ID of the E3. + /// @return e3 The E3 struct. function request( uint256 poolId, uint32[2] calldata threshold, @@ -23,8 +24,21 @@ interface IEnclave { bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3); - /// @notice This function should be called to input data into an Encrypted Execution Environment (E3). + /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3). /// @param e3Id ID of the E3. - /// @param data ABI encoded input data. - function input(uint e3Id, bytes calldata data) external returns (bool success); + /// @param data ABI encoded input data to publish. + /// @return success True if the input was successfully published. + function publishInput(uint256 e3Id, bytes calldata data) external returns (bool success); + + /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3). + /// @param e3Id ID of the E3. + /// @param data ABI encoded output data to verify. + /// @return success True if the output was successfully published. + function publishOutput(uint256 e3Id, bytes memory data) external returns (bool success); + + /// @notice This function should be called to decrypt the output of an Encrypted Execution Environment (E3). + /// @param e3Id ID of the E3. + /// @param data ABI encoded output data to decrypt. + /// @return success True if the output was successfully decrypted. + function decryptOutput(uint256 e3Id, bytes memory data) external returns (bool success); } diff --git a/packages/evm/contracts/Interfaces/IExecutionModule.sol b/packages/evm/contracts/Interfaces/IExecutionModule.sol index d8997678..64ef17a4 100644 --- a/packages/evm/contracts/Interfaces/IExecutionModule.sol +++ b/packages/evm/contracts/Interfaces/IExecutionModule.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; +import { IOutputVerifier } from "./IOutputVerifier.sol"; + interface IExecutionModule { /// @notice This function should be called by the Enclave contract to validate the execution module parameters. /// @param params ABI encoded execution module parameters. - function validate(bytes calldata params) external returns (bool success); + function validate(bytes calldata params) external returns (IOutputVerifier outputVerifier); } diff --git a/packages/evm/contracts/Interfaces/IInputValidator.sol b/packages/evm/contracts/Interfaces/IInputValidator.sol index a54c3afb..1d509ec1 100644 --- a/packages/evm/contracts/Interfaces/IInputValidator.sol +++ b/packages/evm/contracts/Interfaces/IInputValidator.sol @@ -4,5 +4,7 @@ pragma solidity >=0.8.26; interface IInputValidator { /// @notice This function should be called by the Enclave contract to validate the input parameters. /// @param params ABI encoded input parameters. - function validate(address sender, bytes calldata params) external returns (bool success); + /// @return input The input data to be published. + /// @return success Whether the input parameters are valid. + function validate(address sender, bytes memory params) external returns (bytes memory input, bool success); } diff --git a/packages/evm/contracts/Interfaces/IOutputVerifier.sol b/packages/evm/contracts/Interfaces/IOutputVerifier.sol new file mode 100644 index 00000000..e6e1100d --- /dev/null +++ b/packages/evm/contracts/Interfaces/IOutputVerifier.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface IOutputVerifier { + /// @notice This function should be called by the Enclave contract to verify the output of a computation. + /// @param e3Id ID of the E3. + /// @param data ABI encoded output data to be verified. + /// @return output Ciphertext output of the given computation. + function verify(uint256 e3Id, bytes memory data) external returns (bytes memory output, bool success); +} From 89bb9d0c29d14dcd7df3447de83ebe6c692850de Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 09:34:18 +1000 Subject: [PATCH 07/62] move Enclave events to IEnclave --- packages/evm/contracts/Enclave.sol | 11 ------- .../evm/contracts/Interfaces/IEnclave.sol | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 0f2d43f2..63ee9ae0 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -16,17 +16,6 @@ contract Enclave is IEnclave { mapping(address moduleAddress => bool allowed) public executionModules; // Mapping of allowed execution modules. mapping(uint256 id => E3) public e3s; // Mapping of E3s. - event CiphertextOutputPublished(uint256 e3Id, bytes ciphertextOutput); - event E3Requested( - uint256 e3Id, - E3 e3, - uint256 indexed poolId, - IComputationModule indexed computationModule, - IExecutionModule indexed executionModule - ); - event InputPublished(uint256 e3Id, bytes data); - event PlaintextOutputPublished(uint256 e3Id, bytes plaintextOutput); - error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index 99172428..417dc9ee 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -4,6 +4,35 @@ pragma solidity >=0.8.26; import { E3, IComputationModule, IExecutionModule } from "./IE3.sol"; interface IEnclave { + /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published. + /// @param e3Id ID of the E3. + /// @param ciphertextOutput ABI encoded ciphertext output. + event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); + + /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested. + /// @param e3Id ID of the E3. + /// @param e3 Details of the E3. + /// @param poolId ID of the pool of nodes from which the Cypher Node committee was selected. + /// @param computationModule Address of the Computation module selected. + /// @param executionModule Address of the execution module selected. + event E3Requested( + uint256 e3Id, + E3 e3, + uint256 indexed poolId, + IComputationModule indexed computationModule, + IExecutionModule indexed executionModule + ); + + /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published. + /// @param e3Id ID of the E3. + /// @param data ABI encoded input data. + event InputPublished(uint256 indexed e3Id, bytes data); + + /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published. + /// @param e3Id ID of the E3. + /// @param plaintextOutput ABI encoded plaintext output. + event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput); + /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. From ee649088c05c57ebc3903597794186f1e6a5a067 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 09:34:34 +1000 Subject: [PATCH 08/62] fix typo in IE3.sol --- packages/evm/contracts/Interfaces/IE3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/Interfaces/IE3.sol index 2a311314..f6ed28f2 100644 --- a/packages/evm/contracts/Interfaces/IE3.sol +++ b/packages/evm/contracts/Interfaces/IE3.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { IInputValidator } from ".//IInputValidator.sol"; +import { IInputValidator } from "./IInputValidator.sol"; import { IExecutionModule } from "./IExecutionModule.sol"; import { IComputationModule } from "./IComputationModule.sol"; import { IOutputVerifier } from "./IOutputVerifier.sol"; From 647d8cd7d1345def6672bc5e2fc3033a08f5f901 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 09:39:04 +1000 Subject: [PATCH 09/62] format IE3 natspec --- packages/evm/contracts/Interfaces/IE3.sol | 29 ++++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/Interfaces/IE3.sol index f6ed28f2..e160dd14 100644 --- a/packages/evm/contracts/Interfaces/IE3.sol +++ b/packages/evm/contracts/Interfaces/IE3.sol @@ -6,14 +6,25 @@ import { IExecutionModule } from "./IExecutionModule.sol"; import { IComputationModule } from "./IComputationModule.sol"; import { IOutputVerifier } from "./IOutputVerifier.sol"; +/// @title E3 struct +/// @notice This struct represents an E3 computation. +/// @param threshold M/N threshold for the committee. +/// @param expiration Timestamp when committee duties expire. +/// @param computationModule Address of the computation module contract. +/// @param executionModule Address of the execution module contract. +/// @param inputValidator Address of the input validator contract. +/// @param outputVerifier Address of the output verifier contract. +/// @param committeeId ID of the selected committee. +/// @param ciphertextOutput Encrypted output data. +/// @param plaintextOutput Decrypted output data. struct E3 { - uint32[2] threshold; // M/N threshold for the committee. - uint256 expiration; // timestamp when committee duties expire. - IComputationModule computationModule; // address of the computation module contract. - IExecutionModule executionModule; // address of the execution module contract. - IInputValidator inputValidator; // address of the input validator contract. - IOutputVerifier outputVerifier; // address of the output verifier contract. - bytes32 committeeId; // ID of the selected committee. - bytes ciphertextOutput; // encrypted output data. - bytes plaintextOutput; // decrypted output data. + uint32[2] threshold; + uint256 expiration; + IComputationModule computationModule; + IExecutionModule executionModule; + IInputValidator inputValidator; + IOutputVerifier outputVerifier; + bytes32 committeeId; + bytes ciphertextOutput; + bytes plaintextOutput; } From 922b89b4c8636a25317eff0688606386366bdcf5 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 09:44:14 +1000 Subject: [PATCH 10/62] re-order IEnclave events --- packages/evm/contracts/Interfaces/IEnclave.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index 417dc9ee..9e45584d 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -4,11 +4,6 @@ pragma solidity >=0.8.26; import { E3, IComputationModule, IExecutionModule } from "./IE3.sol"; interface IEnclave { - /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published. - /// @param e3Id ID of the E3. - /// @param ciphertextOutput ABI encoded ciphertext output. - event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); - /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested. /// @param e3Id ID of the E3. /// @param e3 Details of the E3. @@ -33,6 +28,11 @@ interface IEnclave { /// @param plaintextOutput ABI encoded plaintext output. event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput); + /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published. + /// @param e3Id ID of the E3. + /// @param ciphertextOutput ABI encoded ciphertext output. + event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); + /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. From de7557d4164220772b55a9736fbb6a097281e4e8 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 09:55:46 +1000 Subject: [PATCH 11/62] add getE3() --- packages/evm/contracts/Enclave.sol | 4 ++++ packages/evm/contracts/Interfaces/IEnclave.sol | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 63ee9ae0..917f10a5 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -109,4 +109,8 @@ contract Enclave is IEnclave { emit PlaintextOutputPublished(e3Id, output); } + + function getE3(uint256 e3Id) external view returns (E3 memory e3) { + return e3s[e3Id]; + } } diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index 9e45584d..41906a0e 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -70,4 +70,9 @@ interface IEnclave { /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. function decryptOutput(uint256 e3Id, bytes memory data) external returns (bool success); + + /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3). + /// @param e3Id ID of the E3. + /// @return e3 The struct representing the requested E3. + function getE3(uint256 e3Id) external view returns (E3 memory e3); } From 24f23e81adedd3357a851337ce9408fffbddeb40 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 10:08:35 +1000 Subject: [PATCH 12/62] add a TODO for allowlists --- packages/evm/contracts/Enclave.sol | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 917f10a5..2d800e1f 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -12,10 +12,18 @@ contract Enclave is IEnclave { uint256 public nexte3Id; // ID of the next E3. uint256 public requests; // total number of requests made to Enclave. - mapping(address moduleAddress => bool allowed) public computationModules; // Mapping of allowed computation modules. - mapping(address moduleAddress => bool allowed) public executionModules; // Mapping of allowed execution modules. + // TODO: should computation and execution modules be explicitly allowed? + // My intuition is that an allowlist is required since they impose slashing conditions. + // But perhaps this is one place where node pools might be utilized, allowing nodes to + // opt in to being selected for specific computations, along with the corresponding slashing conditions. + // This would reduce the governance overhead for Enclave. + mapping(IComputationModule => bool allowed) public computationModules; // Mapping of allowed computation modules. + mapping(IExecutionModule => bool allowed) public executionModules; // Mapping of allowed execution modules. + mapping(uint256 id => E3) public e3s; // Mapping of E3s. + error ComputationModuleNotAllowed(); + error ExecutionModuleNotAllowed(); error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); @@ -47,6 +55,8 @@ contract Enclave is IEnclave { require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); require(duration > 0 && duration <= maxDuration, InvalidDuration()); + require(computationModules[computationModule], ComputationModuleNotAllowed()); + require(executionModules[executionModule], ExecutionModuleNotAllowed()); e3Id = nexte3Id; nexte3Id++; From 7ac26a4315b8c7fb2a060604c098af3afddfd0b0 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 10:43:13 +1000 Subject: [PATCH 13/62] add e3id to node selection --- packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol index 43167eb4..4d8bd088 100644 --- a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol +++ b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol @@ -3,8 +3,13 @@ pragma solidity >=0.8.26; interface ICypherNodeRegistry { /// @notice This function should be called by the Enclave contract to select a node committee. + /// @param e3Id ID of the E3 for which to select the committee. /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @return committeeId ID of the selected committee. - function selectCommittee(uint256 poolId, uint32[2] calldata threshold) external returns (bytes32 committeeId); + function selectCommittee( + uint256 e3Id, + uint256 poolId, + uint32[2] calldata threshold + ) external returns (bytes32 committeeId); } From 522a91b8968adfc815014041adc7eaa7b6621206 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 10:43:31 +1000 Subject: [PATCH 14/62] add dev tags to IEnclave --- packages/evm/contracts/Enclave.sol | 5 +++-- packages/evm/contracts/Interfaces/IEnclave.sol | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 2d800e1f..8d6085c5 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -58,6 +58,7 @@ contract Enclave is IEnclave { require(computationModules[computationModule], ComputationModuleNotAllowed()); require(executionModules[executionModule], ExecutionModuleNotAllowed()); + // TODO: should IDs be incremental or produced deterministic? e3Id = nexte3Id; nexte3Id++; @@ -68,7 +69,7 @@ contract Enclave is IEnclave { IOutputVerifier outputVerifier = executionModule.validate(emParams); require(address(outputVerifier) != address(0), InvalidExecutionModuleSetup()); - bytes32 committeeId = cypherNodeRegistry.selectCommittee(poolId, threshold); + bytes32 committeeId = cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold); // TODO: validate that the selected pool accepts both the computation and execution modules. e3 = E3({ @@ -109,7 +110,7 @@ contract Enclave is IEnclave { emit CiphertextOutputPublished(e3Id, output); } - function decryptOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 storage e3 = e3s[e3Id]; require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index 41906a0e..b92d366b 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -34,6 +34,7 @@ interface IEnclave { event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). + /// @dev This function MUST emit the E3Requested event. /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @param duration The duration of the computation in seconds. @@ -54,24 +55,29 @@ interface IEnclave { ) external payable returns (uint256 e3Id, E3 memory e3); /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3). + /// @dev This function MUST emit the InputPublished event. /// @param e3Id ID of the E3. /// @param data ABI encoded input data to publish. /// @return success True if the input was successfully published. function publishInput(uint256 e3Id, bytes calldata data) external returns (bool success); /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3). + /// @dev This function MUST emit the CiphertextOutputPublished event. /// @param e3Id ID of the E3. /// @param data ABI encoded output data to verify. /// @return success True if the output was successfully published. function publishOutput(uint256 e3Id, bytes memory data) external returns (bool success); /// @notice This function should be called to decrypt the output of an Encrypted Execution Environment (E3). + /// @dev This function MUST revert if the output has not been published. + /// @dev This function MUST emit the PlaintextOutputPublished event. /// @param e3Id ID of the E3. /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. - function decryptOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success); /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3). + /// @dev This function MUST revert if the E3 does not exist. /// @param e3Id ID of the E3. /// @return e3 The struct representing the requested E3. function getE3(uint256 e3Id) external view returns (E3 memory e3); From 729275a00e441aad24d46fe001dbf375d4cfa344 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 11:12:14 +1000 Subject: [PATCH 15/62] add activate() --- packages/evm/contracts/Enclave.sol | 20 ++++++++++++++++--- .../Interfaces/ICypherNodeRegistry.sol | 11 ++++++++-- packages/evm/contracts/Interfaces/IE3.sol | 2 +- .../evm/contracts/Interfaces/IEnclave.sol | 14 +++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 8d6085c5..e18a7050 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -22,7 +22,9 @@ contract Enclave is IEnclave { mapping(uint256 id => E3) public e3s; // Mapping of E3s. + error CommitteeSelectionFailed(); error ComputationModuleNotAllowed(); + error E3AlreadyActivated(uint256 e3Id); error ExecutionModuleNotAllowed(); error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); @@ -69,17 +71,17 @@ contract Enclave is IEnclave { IOutputVerifier outputVerifier = executionModule.validate(emParams); require(address(outputVerifier) != address(0), InvalidExecutionModuleSetup()); - bytes32 committeeId = cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold); + require(cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold), CommitteeSelectionFailed()); // TODO: validate that the selected pool accepts both the computation and execution modules. e3 = E3({ threshold: threshold, - expiration: block.timestamp + duration, + expiration: 0, computationModule: computationModule, executionModule: executionModule, inputValidator: inputValidator, outputVerifier: outputVerifier, - committeeId: committeeId, + committeePublicKey: new bytes(0), ciphertextOutput: new bytes(0), plaintextOutput: new bytes(0) }); @@ -88,6 +90,18 @@ contract Enclave is IEnclave { emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); } + function activate(uint256 e3Id) external returns (bool success) { + E3 storage e3 = e3s[e3Id]; + require(e3.expiration == 0, E3AlreadyActivated(e3Id)); + e3.expiration = block.timestamp + maxDuration; + + e3.committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); + success = e3.committeePublicKey.length > 0; + require(success, CommitteeSelectionFailed()); + + emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey); + } + function publishInput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 storage e3 = e3s[e3Id]; require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); diff --git a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol index 4d8bd088..323a7a7b 100644 --- a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol +++ b/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol @@ -6,10 +6,17 @@ interface ICypherNodeRegistry { /// @param e3Id ID of the E3 for which to select the committee. /// @param poolId ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. - /// @return committeeId ID of the selected committee. + /// @return success True if committee selection was successfully initiated. function selectCommittee( uint256 e3Id, uint256 poolId, uint32[2] calldata threshold - ) external returns (bytes32 committeeId); + ) external returns (bool success); + + /// @notice This function should be called by the Enclave contract to get the public key of a committee. + /// @dev This function MUST revert if no committee has been requested for the given E3. + /// @dev This function MUST revert if the committee has not yet published a public key. + /// @param e3Id ID of the E3 for which to get the committee public key. + /// @return publicKey The public key of the committee. + function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey); } diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/Interfaces/IE3.sol index e160dd14..4d2b18a6 100644 --- a/packages/evm/contracts/Interfaces/IE3.sol +++ b/packages/evm/contracts/Interfaces/IE3.sol @@ -24,7 +24,7 @@ struct E3 { IExecutionModule executionModule; IInputValidator inputValidator; IOutputVerifier outputVerifier; - bytes32 committeeId; + bytes committeePublicKey; bytes ciphertextOutput; bytes plaintextOutput; } diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/Interfaces/IEnclave.sol index b92d366b..a6d09d34 100644 --- a/packages/evm/contracts/Interfaces/IEnclave.sol +++ b/packages/evm/contracts/Interfaces/IEnclave.sol @@ -18,6 +18,12 @@ interface IEnclave { IExecutionModule indexed executionModule ); + /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated. + /// @param e3Id ID of the E3. + /// @param expiration Timestamp when committee duties expire. + /// @param committeePublicKey Public key of the committee. + event E3Activated(uint256 e3Id, uint256 expiration, bytes committeePublicKey); + /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published. /// @param e3Id ID of the E3. /// @param data ABI encoded input data. @@ -54,7 +60,15 @@ interface IEnclave { bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3); + /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input. + /// @dev This function MUST emit the E3Activated event. + /// @dev This function MUST revert if the given E3 has not yet been requested. + /// @dev This function MUST revert if the selected node committee has not yet published a public key. + /// @param e3Id ID of the E3. + function activate(uint256 e3Id) external returns (bool success); + /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3). + /// @dev This function MUST revert if the E3 is not yet activated. /// @dev This function MUST emit the InputPublished event. /// @param e3Id ID of the E3. /// @param data ABI encoded input data to publish. From f4a42fdce2fc15ae5f80434f808327afee1fa5dc Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 13:34:47 +1000 Subject: [PATCH 16/62] add test scaffolding --- package.json | 2 + packages/evm/deploy/deploy.ts | 16 ++- packages/evm/tasks/lock.ts | 64 ++---------- packages/evm/test/encalve/Enclave.fixture.ts | 17 ++++ packages/evm/test/encalve/Enclave.spec.ts | 34 +++++++ packages/evm/test/lock/Lock.fixture.ts | 22 ---- packages/evm/test/lock/Lock.ts | 102 ------------------- packages/evm/test/types.ts | 4 +- 8 files changed, 68 insertions(+), 193 deletions(-) create mode 100644 packages/evm/test/encalve/Enclave.fixture.ts create mode 100644 packages/evm/test/encalve/Enclave.spec.ts delete mode 100644 packages/evm/test/lock/Lock.fixture.ts delete mode 100644 packages/evm/test/lock/Lock.ts diff --git a/package.json b/package.json index 9ea89a6b..a4268cf2 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,13 @@ "compile": "yarn evm:compile", "lint": "yarn evm:lint", "typechain": "yarn evm:typechain", + "test": "yarn evm:test", "coverage": "yarn evm:coverage", "evm:install": "cd packages/evm && yarn install", "evm:compile": "cd packages/evm && yarn compile", "evm:lint": "cd packages/evm && yarn lint", "evm:typechain": "cd packages/evm && yarn typechain", + "evm:test": "cd packages/evm && yarn test", "evm:coverage": "cd packages/evm && yarn coverage", "preinstall": "yarn evm:install" } diff --git a/packages/evm/deploy/deploy.ts b/packages/evm/deploy/deploy.ts index f09cf438..60c6f2bb 100644 --- a/packages/evm/deploy/deploy.ts +++ b/packages/evm/deploy/deploy.ts @@ -1,24 +1,20 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -const DAY_IN_SECONDS = 60 * 60 * 24; -const NOW_IN_SECONDS = Math.round(Date.now() / 1000); -const UNLOCK_IN_X_DAYS = NOW_IN_SECONDS + DAY_IN_SECONDS * 1; // 1 DAY +const THIRTY_DAYS_IN_SECONDS = 60 * 60 * 24 * 30; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await hre.getNamedAccounts(); const { deploy } = hre.deployments; - const lockedAmount = hre.ethers.parseEther("0.01").toString(); - const lock = await deploy("Lock", { + const enclave = await deploy("Enclave", { from: deployer, - args: [UNLOCK_IN_X_DAYS], + args: [THIRTY_DAYS_IN_SECONDS], log: true, - value: lockedAmount, }); - console.log(`Lock contract: `, lock.address); + console.log(`Enclave contract: `, enclave.address); }; export default func; -func.id = "deploy_lock"; // id required to prevent reexecution -func.tags = ["Lock"]; +func.id = "deploy_enclave"; // id required to prevent reexecution +func.tags = ["Enclave"]; diff --git a/packages/evm/tasks/lock.ts b/packages/evm/tasks/lock.ts index 47aa8c2a..d2af2f67 100644 --- a/packages/evm/tasks/lock.ts +++ b/packages/evm/tasks/lock.ts @@ -1,63 +1,13 @@ import { task } from "hardhat/config"; import type { TaskArguments } from "hardhat/types"; -function distance(past: number, future: number): string { - // get total seconds between the times - let delta = future - past; - - // calculate (and subtract) whole days - const days = Math.floor(delta / 86400); - delta -= days * 86400; - - // calculate (and subtract) whole hours - const hours = Math.floor(delta / 3600) % 24; - delta -= hours * 3600; - - // calculate (and subtract) whole minutes - const minutes = Math.floor(delta / 60) % 60; - delta -= minutes * 60; - - // what's left is seconds - const seconds = delta % 60; // in theory the modulus is not required - - return `${days} day(s), ${hours} hour(s), ${minutes} minute(s) and ${seconds} second(s)`; -} - -task("task:withdraw", "Calls the withdraw function of Lock Contract") - .addOptionalParam("address", "Optionally specify the Lock address to withdraw") - .addParam("account", "Specify which account [0, 9]") - .setAction(async function (taskArguments: TaskArguments, hre) { - const { ethers, deployments } = hre; - - const Lock = taskArguments.address ? { address: taskArguments.address } : await deployments.get("Lock"); - - const signers = await ethers.getSigners(); - console.log(taskArguments.address); - - const lock = await ethers.getContractAt("Lock", Lock.address); - - const initialBalance = await ethers.provider.getBalance(Lock.address); - await lock.connect(signers[taskArguments.account]).withdraw(); - const finalBalance = await ethers.provider.getBalance(Lock.address); - - console.log("Contract balance before withdraw", ethers.formatEther(initialBalance)); - console.log("Contract balance after withdraw", ethers.formatEther(finalBalance)); - - console.log("Lock Withdraw Success"); - }); - -task("task:deployLock", "Deploys Lock Contract") - .addParam("unlock", "When to unlock funds in seconds (number of seconds into the futrue)") - .addParam("value", "How much ether you intend locking (in ether not wei, e.g., 0.1)") +task("task:deployEnclave", "Deploys Enclave contract") + .addParam("maxDuration", "The maximum duration of a computation in seconds") .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const NOW_IN_SECONDS = Math.round(Date.now() / 1000); - const signers = await ethers.getSigners(); - const lockedAmount = ethers.parseEther(taskArguments.value); - const unlockTime = NOW_IN_SECONDS + parseInt(taskArguments.unlock); - const lockFactory = await ethers.getContractFactory("Lock"); - console.log(`Deploying Lock and locking ${taskArguments.value} ETH for ${distance(NOW_IN_SECONDS, unlockTime)}`); - const lock = await lockFactory.connect(signers[0]).deploy(unlockTime, { value: lockedAmount }); - await lock.waitForDeployment(); - console.log("Lock deployed to: ", await lock.getAddress()); + const enclaveFactory = await ethers.getContractFactory("Enclave"); + console.log(`Deploying Enclave...`); + const enclave = await enclaveFactory.connect(signers[0]).deploy(taskArguments.maxDuration); + await enclave.waitForDeployment(); + console.log("Enclave deployed to: ", await enclave.getAddress()); }); diff --git a/packages/evm/test/encalve/Enclave.fixture.ts b/packages/evm/test/encalve/Enclave.fixture.ts new file mode 100644 index 00000000..9dffe595 --- /dev/null +++ b/packages/evm/test/encalve/Enclave.fixture.ts @@ -0,0 +1,17 @@ +import { time } from "@nomicfoundation/hardhat-network-helpers"; +import { ethers } from "hardhat"; + +import type { Enclave } from "../../types/Enclave"; +import type { Enclave__factory } from "../../types/factories/Enclave__factory"; + +export async function deployEnclaveFixture() { + // Contracts are deployed using the first signer/account by default + const [owner, otherAccount] = await ethers.getSigners(); + const maxDuration = 60 * 60 * 24 * 30; + + const Enclave = (await ethers.getContractFactory("Enclave")) as Enclave__factory; + const enclave = (await Enclave.deploy(maxDuration)) as Enclave; + const enclave_address = await enclave.getAddress(); + + return { enclave, enclave_address, maxDuration, owner, otherAccount }; +} diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts new file mode 100644 index 00000000..1144551c --- /dev/null +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -0,0 +1,34 @@ +import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; +import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; +import { expect } from "chai"; +import { ethers } from "hardhat"; + +import type { Signers } from "../types"; +import { deployEnclaveFixture } from "./Enclave.fixture"; + +describe("Enclave", function () { + before(async function () { + this.signers = {} as Signers; + + const signers = await ethers.getSigners(); + this.signers.admin = signers[0]; + + this.loadFixture = loadFixture; + }); + + describe("Deployment", function () { + beforeEach(async function () { + const { enclave, enclave_address, maxDuration, owner } = await this.loadFixture(deployEnclaveFixture); + this.enclave = enclave; + this.enclave_address = enclave_address; + this.maxDuration = maxDuration; + this.owner = owner; + }); + + it("Should correctly set max duration", async function () { + // We don't use the fixture here because we want a different deployment + const maxDuration = await this.enclave.maxDuration(); + expect(maxDuration).to.equal(this.maxDuration); + }); + }); +}); diff --git a/packages/evm/test/lock/Lock.fixture.ts b/packages/evm/test/lock/Lock.fixture.ts deleted file mode 100644 index 4ffe253e..00000000 --- a/packages/evm/test/lock/Lock.fixture.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { time } from "@nomicfoundation/hardhat-network-helpers"; -import { ethers } from "hardhat"; - -import type { Lock } from "../../types/Lock"; -import type { Lock__factory } from "../../types/factories/Lock__factory"; - -export async function deployLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await ethers.getSigners(); - - const Lock = (await ethers.getContractFactory("Lock")) as Lock__factory; - const lock = (await Lock.deploy(unlockTime, { value: lockedAmount })) as Lock; - const lock_address = await lock.getAddress(); - - return { lock, lock_address, unlockTime, lockedAmount, owner, otherAccount }; -} diff --git a/packages/evm/test/lock/Lock.ts b/packages/evm/test/lock/Lock.ts deleted file mode 100644 index 932df747..00000000 --- a/packages/evm/test/lock/Lock.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; -import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; -import { expect } from "chai"; -import { ethers } from "hardhat"; - -import type { Signers } from "../types"; -import { deployLockFixture } from "./Lock.fixture"; - -describe("Lock", function () { - before(async function () { - this.signers = {} as Signers; - - const signers = await ethers.getSigners(); - this.signers.admin = signers[0]; - - this.loadFixture = loadFixture; - }); - - describe("Deployment", function () { - beforeEach(async function () { - const { lock, lock_address, unlockTime, owner, lockedAmount } = await this.loadFixture(deployLockFixture); - this.lock = lock; - this.lock_address = lock_address; - this.unlockTime = unlockTime; - this.owner = owner; - this.lockedAmount = lockedAmount; - }); - - it("Should fail if the unlockTime is not in the future", async function () { - // We don't use the fixture here because we want a different deployment - const latestTime = await time.latest(); - const Lock = await ethers.getContractFactory("Lock"); - await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWithCustomError(Lock, "InvalidUnlockTime"); - }); - - it("Should set the right unlockTime", async function () { - expect(await this.lock.unlockTime()).to.equal(this.unlockTime); - }); - - it("Should set the right owner", async function () { - expect(await this.lock.owner()).to.equal(this.owner.address); - }); - - it("Should receive and store the funds to lock", async function () { - expect(await ethers.provider.getBalance(this.lock_address)).to.equal(this.lockedAmount); - }); - }); - - describe("Withdrawals", function () { - beforeEach(async function () { - const { lock, unlockTime, owner, lockedAmount, otherAccount } = await this.loadFixture(deployLockFixture); - this.lock = lock; - this.unlockTime = unlockTime; - this.owner = owner; - this.lockedAmount = lockedAmount; - this.otherAccount = otherAccount; - }); - - describe("Validations", function () { - it("Should revert with the right error if called too soon", async function () { - await expect(this.lock.withdraw()).to.be.revertedWithCustomError(this.lock, "UnlockTimeNotReached"); - }); - - it("Should revert with the right error if called from another account", async function () { - // We can increase the time in Hardhat Network - await time.increaseTo(this.unlockTime); - - // We use lock.connect() to send a transaction from another account - await expect(this.lock.connect(this.otherAccount).withdraw()).to.be.revertedWithCustomError( - this.lock, - "NotOwner", - ); - }); - - it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () { - // Transactions are sent using the first signer by default - await time.increaseTo(this.unlockTime); - - await expect(this.lock.withdraw()).not.to.be.reverted; - }); - }); - - describe("Events", function () { - it("Should emit an event on withdrawals", async function () { - await time.increaseTo(this.unlockTime); - - await expect(this.lock.withdraw()).to.emit(this.lock, "Withdrawal").withArgs(this.lockedAmount, anyValue); // We accept any value as `when` arg - }); - }); - - describe("Transfers", function () { - it("Should transfer the funds to the owner", async function () { - await time.increaseTo(this.unlockTime); - - await expect(this.lock.withdraw()).to.changeEtherBalances( - [this.owner, this.lock], - [this.lockedAmount, -this.lockedAmount], - ); - }); - }); - }); -}); diff --git a/packages/evm/test/types.ts b/packages/evm/test/types.ts index 645314ee..37487397 100644 --- a/packages/evm/test/types.ts +++ b/packages/evm/test/types.ts @@ -1,12 +1,12 @@ import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/dist/src/signer-with-address"; -import type { Lock } from "../types/Lock"; +import type { Enclave } from "../types/Enclave"; type Fixture = () => Promise; declare module "mocha" { export interface Context { - lock: Lock; + enclave: Enclave; loadFixture: (fixture: Fixture) => Promise; signers: Signers; } From 000dc33a4086dfd68d85a4a9e6af3952b244d45f Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 13:48:12 +1000 Subject: [PATCH 17/62] fix: lowercase folder names --- packages/evm/contracts/Enclave.sol | 8 ++++---- .../{Interfaces => interfaces}/IComputationModule.sol | 0 .../{Interfaces => interfaces}/ICypherNodeRegistry.sol | 0 packages/evm/contracts/{Interfaces => interfaces}/IE3.sol | 0 .../evm/contracts/{Interfaces => interfaces}/IEnclave.sol | 0 .../{Interfaces => interfaces}/IExecutionModule.sol | 0 .../{Interfaces => interfaces}/IInputValidator.sol | 0 .../{Interfaces => interfaces}/IOutputVerifier.sol | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename packages/evm/contracts/{Interfaces => interfaces}/IComputationModule.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/ICypherNodeRegistry.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/IE3.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/IEnclave.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/IExecutionModule.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/IInputValidator.sol (100%) rename packages/evm/contracts/{Interfaces => interfaces}/IOutputVerifier.sol (100%) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index e18a7050..8b4aa319 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { IEnclave, E3, IComputationModule, IExecutionModule } from "./Interfaces/IEnclave.sol"; -import { ICypherNodeRegistry } from "./Interfaces/ICypherNodeRegistry.sol"; -import { IInputValidator } from "./Interfaces/IInputValidator.sol"; -import { IOutputVerifier } from "./Interfaces/IOutputVerifier.sol"; +import { IEnclave, E3, IComputationModule, IExecutionModule } from "./interfaces/IEnclave.sol"; +import { ICypherNodeRegistry } from "./interfaces/ICypherNodeRegistry.sol"; +import { IInputValidator } from "./interfaces/IInputValidator.sol"; +import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; contract Enclave is IEnclave { ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. diff --git a/packages/evm/contracts/Interfaces/IComputationModule.sol b/packages/evm/contracts/interfaces/IComputationModule.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IComputationModule.sol rename to packages/evm/contracts/interfaces/IComputationModule.sol diff --git a/packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol similarity index 100% rename from packages/evm/contracts/Interfaces/ICypherNodeRegistry.sol rename to packages/evm/contracts/interfaces/ICypherNodeRegistry.sol diff --git a/packages/evm/contracts/Interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IE3.sol rename to packages/evm/contracts/interfaces/IE3.sol diff --git a/packages/evm/contracts/Interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IEnclave.sol rename to packages/evm/contracts/interfaces/IEnclave.sol diff --git a/packages/evm/contracts/Interfaces/IExecutionModule.sol b/packages/evm/contracts/interfaces/IExecutionModule.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IExecutionModule.sol rename to packages/evm/contracts/interfaces/IExecutionModule.sol diff --git a/packages/evm/contracts/Interfaces/IInputValidator.sol b/packages/evm/contracts/interfaces/IInputValidator.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IInputValidator.sol rename to packages/evm/contracts/interfaces/IInputValidator.sol diff --git a/packages/evm/contracts/Interfaces/IOutputVerifier.sol b/packages/evm/contracts/interfaces/IOutputVerifier.sol similarity index 100% rename from packages/evm/contracts/Interfaces/IOutputVerifier.sol rename to packages/evm/contracts/interfaces/IOutputVerifier.sol From 469265a7cb56ab27c5240ead93b2b0e20e00a8f2 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 28 May 2024 13:50:19 +1000 Subject: [PATCH 18/62] fix path --- packages/evm/.eslintrc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/.eslintrc.yml b/packages/evm/.eslintrc.yml index 27672a35..e19402e0 100644 --- a/packages/evm/.eslintrc.yml +++ b/packages/evm/.eslintrc.yml @@ -5,7 +5,7 @@ extends: - "prettier" parser: "@typescript-eslint/parser" parserOptions: - project: "tsconfig.json" + project: "packages/evm/tsconfig.json" plugins: - "@typescript-eslint" root: true From 655cc8a74cc3151c2d4eeb300ddaa4eca172e4f1 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 29 May 2024 09:48:30 +1000 Subject: [PATCH 19/62] add mock contracts --- .../contracts/test/MockComputationModule.sol | 14 ++++++++++++++ .../contracts/test/MockCypherNodeRegistry.sol | 18 ++++++++++++++++++ .../evm/contracts/test/MockExecutionModule.sol | 10 ++++++++++ .../evm/contracts/test/MockInputValidator.sol | 11 +++++++++++ .../evm/contracts/test/MockOutputVerifier.sol | 11 +++++++++++ 5 files changed, 64 insertions(+) create mode 100644 packages/evm/contracts/test/MockComputationModule.sol create mode 100644 packages/evm/contracts/test/MockCypherNodeRegistry.sol create mode 100644 packages/evm/contracts/test/MockExecutionModule.sol create mode 100644 packages/evm/contracts/test/MockInputValidator.sol create mode 100644 packages/evm/contracts/test/MockOutputVerifier.sol diff --git a/packages/evm/contracts/test/MockComputationModule.sol b/packages/evm/contracts/test/MockComputationModule.sol new file mode 100644 index 00000000..a7220bdf --- /dev/null +++ b/packages/evm/contracts/test/MockComputationModule.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IComputationModule, IInputValidator } from "../interfaces/IComputationModule.sol"; + +contract MockComputationModule is IComputationModule { + function validate(bytes calldata params) external pure returns (IInputValidator inputValidator) { + (inputValidator) = abi.decode(params, (IInputValidator)); + } + + function verify(uint256, bytes memory outputData) external pure returns (bytes memory output, bool success) { + return (outputData, true); + } +} diff --git a/packages/evm/contracts/test/MockCypherNodeRegistry.sol b/packages/evm/contracts/test/MockCypherNodeRegistry.sol new file mode 100644 index 00000000..e3f921e6 --- /dev/null +++ b/packages/evm/contracts/test/MockCypherNodeRegistry.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; + +contract MockCypherNodeRegistry is ICypherNodeRegistry { + function selectCommittee(uint256, uint256 poolId, uint32[2] calldata) external pure returns (bool success) { + if (poolId == 0) { + success = false; + } else { + success = true; + } + } + + function getCommitteePublicKey(uint256 e3Id) external pure returns (bytes memory) { + return new bytes(e3Id); + } +} diff --git a/packages/evm/contracts/test/MockExecutionModule.sol b/packages/evm/contracts/test/MockExecutionModule.sol new file mode 100644 index 00000000..93beb81b --- /dev/null +++ b/packages/evm/contracts/test/MockExecutionModule.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IExecutionModule, IOutputVerifier } from "../interfaces/IExecutionModule.sol"; + +contract MockExecutionModule is IExecutionModule { + function validate(bytes calldata params) external pure returns (IOutputVerifier outputVerifier) { + (outputVerifier) = abi.decode(params, (IOutputVerifier)); + } +} diff --git a/packages/evm/contracts/test/MockInputValidator.sol b/packages/evm/contracts/test/MockInputValidator.sol new file mode 100644 index 00000000..a76909d6 --- /dev/null +++ b/packages/evm/contracts/test/MockInputValidator.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IInputValidator } from "../interfaces/IInputValidator.sol"; + +contract MockInputValidator is IInputValidator { + function validate(address, bytes memory params) external pure returns (bytes memory input, bool success) { + (input) = abi.decode(params, (bytes)); + success = true; + } +} diff --git a/packages/evm/contracts/test/MockOutputVerifier.sol b/packages/evm/contracts/test/MockOutputVerifier.sol new file mode 100644 index 00000000..37434b3e --- /dev/null +++ b/packages/evm/contracts/test/MockOutputVerifier.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { IOutputVerifier } from "../interfaces/IOutputVerifier.sol"; + +contract MockOutputVerifier is IOutputVerifier { + function verify(uint256, bytes memory data) external pure returns (bytes memory output, bool success) { + (output) = abi.decode(data, (bytes)); + success = true; + } +} From 14cc9707fa4921f1d478f4de9f0678a3e5bcc8fb Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 30 May 2024 14:02:18 +1000 Subject: [PATCH 20/62] todo: do we need a start timestamp for requests? --- packages/evm/contracts/Enclave.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 8b4aa319..55df70bd 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -47,7 +47,7 @@ contract Enclave is IEnclave { function request( uint256 poolId, uint32[2] calldata threshold, - uint256 duration, + uint256 duration, // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are published before the request is made? This kind of assumes the cypher nodes have already been selected and generated a shared secret. IComputationModule computationModule, bytes memory computationParams, IExecutionModule executionModule, From fa0605d83d921db5335ec209743673f5dbc405af Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 30 May 2024 14:06:20 +1000 Subject: [PATCH 21/62] select committee after instantiating E3 object in storage --- packages/evm/contracts/Enclave.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 55df70bd..6d20dc38 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -17,7 +17,9 @@ contract Enclave is IEnclave { // But perhaps this is one place where node pools might be utilized, allowing nodes to // opt in to being selected for specific computations, along with the corresponding slashing conditions. // This would reduce the governance overhead for Enclave. + // TODO: add setter function mapping(IComputationModule => bool allowed) public computationModules; // Mapping of allowed computation modules. + // TODO: add setter function mapping(IExecutionModule => bool allowed) public executionModules; // Mapping of allowed execution modules. mapping(uint256 id => E3) public e3s; // Mapping of E3s. @@ -71,9 +73,6 @@ contract Enclave is IEnclave { IOutputVerifier outputVerifier = executionModule.validate(emParams); require(address(outputVerifier) != address(0), InvalidExecutionModuleSetup()); - require(cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold), CommitteeSelectionFailed()); - // TODO: validate that the selected pool accepts both the computation and execution modules. - e3 = E3({ threshold: threshold, expiration: 0, @@ -87,6 +86,9 @@ contract Enclave is IEnclave { }); e3s[e3Id] = e3; + require(cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold), CommitteeSelectionFailed()); + // TODO: validate that the selected pool accepts both the computation and execution modules. + emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); } From cda415b2441fa4d3411ce56cfb1832032237cfbe Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 30 May 2024 16:53:01 +1000 Subject: [PATCH 22/62] add "yarn clean" to root package --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index a4268cf2..a10196b9 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "url": "https://github.com/gnosisguild" }, "scripts": { + "clean": "cd packages/evm && yarn clean", "compile": "yarn evm:compile", "lint": "yarn evm:lint", "typechain": "yarn evm:typechain", From 805bf94d68c13e798f04ef83746e2bfbb1d40908 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 30 May 2024 17:05:10 +1000 Subject: [PATCH 23/62] add ownableUpgradable and start scaffolding tests --- packages/evm/contracts/Enclave.sol | 63 +++++++++++++++++-- .../evm/contracts/interfaces/IEnclave.sol | 33 ++++++++++ packages/evm/package.json | 4 +- packages/evm/test/encalve/Enclave.fixture.ts | 7 +-- packages/evm/test/encalve/Enclave.spec.ts | 45 ++++++++++--- .../mocks/MockComputationModule.fixture.ts | 17 +++++ 6 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 packages/evm/test/mocks/MockComputationModule.fixture.ts diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 6d20dc38..06e6460b 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -5,8 +5,15 @@ import { IEnclave, E3, IComputationModule, IExecutionModule } from "./interfaces import { ICypherNodeRegistry } from "./interfaces/ICypherNodeRegistry.sol"; import { IInputValidator } from "./interfaces/IInputValidator.sol"; import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract Enclave is IEnclave, OwnableUpgradeable { + //////////////////////////////////////////////////////////// + // // + // Storage Variables // + // // + //////////////////////////////////////////////////////////// -contract Enclave is IEnclave { ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. uint256 public maxDuration; // TODO: add a setter function. uint256 public nexte3Id; // ID of the next E3. @@ -24,9 +31,16 @@ contract Enclave is IEnclave { mapping(uint256 id => E3) public e3s; // Mapping of E3s. + //////////////////////////////////////////////////////////// + // // + // Errors // + // // + //////////////////////////////////////////////////////////// + error CommitteeSelectionFailed(); error ComputationModuleNotAllowed(); error E3AlreadyActivated(uint256 e3Id); + error E3DoesNotExist(uint256 e3Id); error ExecutionModuleNotAllowed(); error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); @@ -41,11 +55,31 @@ contract Enclave is IEnclave { error PaymentRequired(); error PlaintextOutputAlreadyPublished(uint256 e3Id); - /// @param _maxDuration The maximum duration of a computation in seconds. - constructor(uint256 _maxDuration) { + //////////////////////////////////////////////////////////// + // // + // Initialization // + // // + //////////////////////////////////////////////////////////// + + /// @param _owner The owner of this contract + /// @param _maxDuration The maximum duration of a computation in seconds + constructor(address _owner, uint256 _maxDuration) { + initialize(_owner, _maxDuration); + } + + /// @param _owner The owner of this contract + /// @param _maxDuration The maximum duration of a computation in seconds + function initialize(address _owner, uint256 _maxDuration) public initializer { maxDuration = _maxDuration; + __Ownable_init(_owner); } + //////////////////////////////////////////////////////////// + // // + // Core Entrypoints // + // // + //////////////////////////////////////////////////////////// + function request( uint256 poolId, uint32[2] calldata threshold, @@ -137,7 +171,26 @@ contract Enclave is IEnclave { emit PlaintextOutputPublished(e3Id, output); } - function getE3(uint256 e3Id) external view returns (E3 memory e3) { - return e3s[e3Id]; + //////////////////////////////////////////////////////////// + // // + // Set Functions // + // // + //////////////////////////////////////////////////////////// + + function setMaxDuration(uint256 _maxDuration) external onlyOwner returns (bool success) { + maxDuration = _maxDuration; + success = true; + emit MaxDurationSet(_maxDuration); + } + + //////////////////////////////////////////////////////////// + // // + // Get Functions // + // // + //////////////////////////////////////////////////////////// + + function getE3(uint256 e3Id) public view returns (E3 memory e3) { + e3 = e3s[e3Id]; + require(e3.computationModule != IComputationModule(address(0)), E3DoesNotExist(e3Id)); } } diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index a6d09d34..e5472a45 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -4,6 +4,12 @@ pragma solidity >=0.8.26; import { E3, IComputationModule, IExecutionModule } from "./IE3.sol"; interface IEnclave { + //////////////////////////////////////////////////////////// + // // + // Events // + // // + //////////////////////////////////////////////////////////// + /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested. /// @param e3Id ID of the E3. /// @param e3 Details of the E3. @@ -39,6 +45,16 @@ interface IEnclave { /// @param ciphertextOutput ABI encoded ciphertext output. event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); + /// @notice This event MUST be emitted any time the `maxDuration` is set. + /// @param maxDuration The maximum duration of a computation in seconds. + event MaxDurationSet(uint256 maxDuration); + + //////////////////////////////////////////////////////////// + // // + // Core Entrypoints // + // // + //////////////////////////////////////////////////////////// + /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @dev This function MUST emit the E3Requested event. /// @param poolId ID of the pool of nodes from which to select the committee. @@ -90,6 +106,23 @@ interface IEnclave { /// @return success True if the output was successfully decrypted. function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success); + //////////////////////////////////////////////////////////// + // // + // Set Functions // + // // + //////////////////////////////////////////////////////////// + + /// @notice This function should be called to set the maximum duration of requested computations. + /// @param _maxDuration The maximum duration of a computation in seconds. + /// @return success True if the max duration was successfully set. + function setMaxDuration(uint256 _maxDuration) external returns (bool success); + + //////////////////////////////////////////////////////////// + // // + // Get Functions // + // // + //////////////////////////////////////////////////////////// + /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the E3 does not exist. /// @param e3Id ID of the E3. diff --git a/packages/evm/package.json b/packages/evm/package.json index 9af0ee39..416a24a8 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -12,6 +12,7 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.10", "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", @@ -75,5 +76,6 @@ "task:withdraw": "hardhat task:withdraw", "test": "hardhat test", "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain" - } + }, + "dependencies": {} } diff --git a/packages/evm/test/encalve/Enclave.fixture.ts b/packages/evm/test/encalve/Enclave.fixture.ts index 9dffe595..488a769d 100644 --- a/packages/evm/test/encalve/Enclave.fixture.ts +++ b/packages/evm/test/encalve/Enclave.fixture.ts @@ -1,8 +1,7 @@ -import { time } from "@nomicfoundation/hardhat-network-helpers"; import { ethers } from "hardhat"; -import type { Enclave } from "../../types/Enclave"; -import type { Enclave__factory } from "../../types/factories/Enclave__factory"; +import type { Enclave } from "../../types/contracts/Enclave"; +import type { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; export async function deployEnclaveFixture() { // Contracts are deployed using the first signer/account by default @@ -10,7 +9,7 @@ export async function deployEnclaveFixture() { const maxDuration = 60 * 60 * 24 * 30; const Enclave = (await ethers.getContractFactory("Enclave")) as Enclave__factory; - const enclave = (await Enclave.deploy(maxDuration)) as Enclave; + const enclave = (await Enclave.deploy(owner.address, maxDuration)) as Enclave; const enclave_address = await enclave.getAddress(); return { enclave, enclave_address, maxDuration, owner, otherAccount }; diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 1144551c..30608397 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -3,6 +3,7 @@ import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; +import { deployMockComputationModuleFixture } from "../mocks/MockComputationModule.fixture"; import type { Signers } from "../types"; import { deployEnclaveFixture } from "./Enclave.fixture"; @@ -16,19 +17,45 @@ describe("Enclave", function () { this.loadFixture = loadFixture; }); - describe("Deployment", function () { - beforeEach(async function () { - const { enclave, enclave_address, maxDuration, owner } = await this.loadFixture(deployEnclaveFixture); - this.enclave = enclave; - this.enclave_address = enclave_address; - this.maxDuration = maxDuration; - this.owner = owner; - }); + beforeEach(async function () { + const { enclave, enclave_address, maxDuration, owner } = await this.loadFixture(deployEnclaveFixture); + this.enclave = enclave; + this.enclave_address = enclave_address; + this.maxDuration = maxDuration; + this.owner = owner; + + const { mockComputationModule, mockComputationModule_address } = await this.loadFixture( + deployMockComputationModuleFixture, + ); + this.mockComputationModule = mockComputationModule; + this.mockComputationModule_address = mockComputationModule_address; + }); - it("Should correctly set max duration", async function () { + describe("Deployment", function () { + it("correctly sets max duration", async function () { // We don't use the fixture here because we want a different deployment const maxDuration = await this.enclave.maxDuration(); expect(maxDuration).to.equal(this.maxDuration); }); + + it("correctly sets owner", async function () { + // We don't use the fixture here because we want a different deployment + const owner = await this.enclave.owner(); + expect(owner).to.equal(this.owner); + }); + }); + + describe("setMaxDuration()", function () { + it("reverts if not called by owner"); + it("reverts if duration is 0"); + it("reverts if duration is greater than 30 days"); + it("set max duration correctly"); + it("returns true if max duration is set successfully"); + it("emits MaxDurationChanged event"); + }); + + describe("getE3Id()", function () { + it("reverts if E3 does not exist"); + it("returns correct E3 details"); }); }); diff --git a/packages/evm/test/mocks/MockComputationModule.fixture.ts b/packages/evm/test/mocks/MockComputationModule.fixture.ts new file mode 100644 index 00000000..3d6f6c41 --- /dev/null +++ b/packages/evm/test/mocks/MockComputationModule.fixture.ts @@ -0,0 +1,17 @@ +import { ethers } from "hardhat"; + +import type { MockComputationModule } from "../../types/contracts/test/MockComputationModule"; +import type { MockComputationModule__factory } from "../../types/factories/contracts/test/MockComputationModule__factory"; + +export async function deployMockComputationModuleFixture() { + // Contracts are deployed using the first signer/account by default + const [owner, otherAccount] = await ethers.getSigners(); + + const MockComputationModule = (await ethers.getContractFactory( + "MockComputationModule", + )) as MockComputationModule__factory; + const mockComputationModule = (await MockComputationModule.deploy()) as MockComputationModule; + const mockComputationModule_address = await mockComputationModule.getAddress(); + + return { mockComputationModule, mockComputationModule_address, owner, otherAccount }; +} From 15104ecd08692c5b7eef2cb90d52b7785519d6da Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 31 May 2024 12:46:14 +1000 Subject: [PATCH 24/62] change initialization flow to allow _owner to differ from msg.sender --- packages/evm/contracts/Enclave.sol | 7 ++++--- packages/evm/test/encalve/Enclave.fixture.ts | 2 +- packages/evm/test/encalve/Enclave.spec.ts | 21 +++++++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 06e6460b..634b58c3 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -70,8 +70,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds function initialize(address _owner, uint256 _maxDuration) public initializer { - maxDuration = _maxDuration; - __Ownable_init(_owner); + __Ownable_init(msg.sender); + setMaxDuration(_maxDuration); + if (_owner != owner()) transferOwnership(_owner); } //////////////////////////////////////////////////////////// @@ -177,7 +178,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// - function setMaxDuration(uint256 _maxDuration) external onlyOwner returns (bool success) { + function setMaxDuration(uint256 _maxDuration) public onlyOwner returns (bool success) { maxDuration = _maxDuration; success = true; emit MaxDurationSet(_maxDuration); diff --git a/packages/evm/test/encalve/Enclave.fixture.ts b/packages/evm/test/encalve/Enclave.fixture.ts index 488a769d..c60db2bb 100644 --- a/packages/evm/test/encalve/Enclave.fixture.ts +++ b/packages/evm/test/encalve/Enclave.fixture.ts @@ -12,5 +12,5 @@ export async function deployEnclaveFixture() { const enclave = (await Enclave.deploy(owner.address, maxDuration)) as Enclave; const enclave_address = await enclave.getAddress(); - return { enclave, enclave_address, maxDuration, owner, otherAccount }; + return { Enclave, enclave, enclave_address, maxDuration, owner, otherAccount }; } diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 30608397..871f1704 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -18,11 +18,14 @@ describe("Enclave", function () { }); beforeEach(async function () { - const { enclave, enclave_address, maxDuration, owner } = await this.loadFixture(deployEnclaveFixture); + const { Enclave, enclave, enclave_address, maxDuration, owner, otherAccount } = + await this.loadFixture(deployEnclaveFixture); + this.Enclave = Enclave; this.enclave = enclave; this.enclave_address = enclave_address; this.maxDuration = maxDuration; this.owner = owner; + this.otherAccount = otherAccount; const { mockComputationModule, mockComputationModule_address } = await this.loadFixture( deployMockComputationModuleFixture, @@ -33,15 +36,23 @@ describe("Enclave", function () { describe("Deployment", function () { it("correctly sets max duration", async function () { - // We don't use the fixture here because we want a different deployment const maxDuration = await this.enclave.maxDuration(); + expect(maxDuration).to.equal(this.maxDuration); }); it("correctly sets owner", async function () { - // We don't use the fixture here because we want a different deployment - const owner = await this.enclave.owner(); - expect(owner).to.equal(this.owner); + // uses the fixture deployment with this.owner set as the owner + const owner1 = await this.enclave.owner(); + // create a new deployment with this.otherAccount as the owner + // note that this.owner is msg.sender in both cases + const enclave = await this.Enclave.deploy(this.otherAccount.address, this.maxDuration); + const owner2 = await enclave.owner(); + + // expect the owner to be the same as the one set in the fixture + expect(owner1).to.equal(this.owner); + // expect the owner to be the same as the one set in the new deployment + expect(owner2).to.equal(this.otherAccount); }); }); From e9998071d69b3ef666b3927706a93601e73c3314 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 31 May 2024 15:58:19 +1000 Subject: [PATCH 25/62] add tests for setters --- packages/evm/contracts/Enclave.sol | 55 ++++- .../evm/contracts/interfaces/IEnclave.sol | 20 ++ packages/evm/test/encalve/Enclave.fixture.ts | 2 +- packages/evm/test/encalve/Enclave.spec.ts | 214 ++++++++++++++++-- 4 files changed, 269 insertions(+), 22 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 634b58c3..2b82f7f8 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -41,11 +41,13 @@ contract Enclave is IEnclave, OwnableUpgradeable { error ComputationModuleNotAllowed(); error E3AlreadyActivated(uint256 e3Id); error E3DoesNotExist(uint256 e3Id); - error ExecutionModuleNotAllowed(); + error ModuleAlreadyEnabled(address module); + error ModuleNotEnabled(address module); error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); error InvalidExecutionModuleSetup(); + error InvalidCypherNodeRegistry(ICypherNodeRegistry cypherNodeRegistry); error InvalidInput(); error InvalidDuration(); error InvalidOutput(); @@ -63,15 +65,20 @@ contract Enclave is IEnclave, OwnableUpgradeable { /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds - constructor(address _owner, uint256 _maxDuration) { - initialize(_owner, _maxDuration); + constructor(address _owner, ICypherNodeRegistry _cypherNodeRegistry, uint256 _maxDuration) { + initialize(_owner, _cypherNodeRegistry, _maxDuration); } /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds - function initialize(address _owner, uint256 _maxDuration) public initializer { + function initialize( + address _owner, + ICypherNodeRegistry _cypherNodeRegistry, + uint256 _maxDuration + ) public initializer { __Ownable_init(msg.sender); setMaxDuration(_maxDuration); + setCypherNodeRegistry(_cypherNodeRegistry); if (_owner != owner()) transferOwnership(_owner); } @@ -95,7 +102,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); require(duration > 0 && duration <= maxDuration, InvalidDuration()); require(computationModules[computationModule], ComputationModuleNotAllowed()); - require(executionModules[executionModule], ExecutionModuleNotAllowed()); + require(executionModules[executionModule], ModuleNotEnabled(address(executionModule))); // TODO: should IDs be incremental or produced deterministic? e3Id = nexte3Id; @@ -184,6 +191,44 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit MaxDurationSet(_maxDuration); } + function setCypherNodeRegistry(ICypherNodeRegistry _cypherNodeRegistry) public onlyOwner returns (bool success) { + require( + address(_cypherNodeRegistry) != address(0) && _cypherNodeRegistry != cypherNodeRegistry, + InvalidCypherNodeRegistry(_cypherNodeRegistry) + ); + cypherNodeRegistry = _cypherNodeRegistry; + success = true; + emit CypherNodeRegistrySet(address(_cypherNodeRegistry)); + } + + function enableComputationModule(IComputationModule computationModule) public onlyOwner returns (bool success) { + require(!computationModules[computationModule], ModuleAlreadyEnabled(address(computationModule))); + computationModules[computationModule] = true; + success = true; + emit ComputationModuleEnabled(computationModule); + } + + function enableExecutionModule(IExecutionModule executionModule) public onlyOwner returns (bool success) { + require(!executionModules[executionModule], ModuleAlreadyEnabled(address(executionModule))); + executionModules[executionModule] = true; + success = true; + emit ExecutionModuleEnabled(executionModule); + } + + function disableComputationModule(IComputationModule computationModule) public onlyOwner returns (bool success) { + require(computationModules[computationModule], ModuleNotEnabled(address(computationModule))); + delete computationModules[computationModule]; + success = true; + emit ComputationModuleDisabled(computationModule); + } + + function disableExecutionModule(IExecutionModule executionModule) public onlyOwner returns (bool success) { + require(executionModules[executionModule], ModuleNotEnabled(address(executionModule))); + delete executionModules[executionModule]; + success = true; + emit ExecutionModuleDisabled(executionModule); + } + //////////////////////////////////////////////////////////// // // // Get Functions // diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index e5472a45..ddf8a376 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -49,6 +49,26 @@ interface IEnclave { /// @param maxDuration The maximum duration of a computation in seconds. event MaxDurationSet(uint256 maxDuration); + /// @notice This event MUST be emitted any time the CypherNodeRegistry is set. + /// @param cypherNodeRegistry The address of the CypherNodeRegistry contract. + event CypherNodeRegistrySet(address cypherNodeRegistry); + + /// @notice This event MUST be emitted any time a computation module is enabled. + /// @param computationModule The address of the computation module. + event ComputationModuleEnabled(IComputationModule computationModule); + + /// @notice This event MUST be emitted any time a computation module is disabled. + /// @param computationModule The address of the computation module. + event ComputationModuleDisabled(IComputationModule computationModule); + + /// @notice This event MUST be emitted any time an execution module is enabled. + /// @param executionModule The address of the execution module. + event ExecutionModuleEnabled(IExecutionModule executionModule); + + /// @notice This event MUST be emitted any time an execution module is disabled. + /// @param executionModule The address of the execution module. + event ExecutionModuleDisabled(IExecutionModule executionModule); + //////////////////////////////////////////////////////////// // // // Core Entrypoints // diff --git a/packages/evm/test/encalve/Enclave.fixture.ts b/packages/evm/test/encalve/Enclave.fixture.ts index c60db2bb..3c259eda 100644 --- a/packages/evm/test/encalve/Enclave.fixture.ts +++ b/packages/evm/test/encalve/Enclave.fixture.ts @@ -9,7 +9,7 @@ export async function deployEnclaveFixture() { const maxDuration = 60 * 60 * 24 * 30; const Enclave = (await ethers.getContractFactory("Enclave")) as Enclave__factory; - const enclave = (await Enclave.deploy(owner.address, maxDuration)) as Enclave; + const enclave = (await Enclave.deploy(owner.address, otherAccount.address, maxDuration)) as Enclave; const enclave_address = await enclave.getAddress(); return { Enclave, enclave, enclave_address, maxDuration, owner, otherAccount }; diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 871f1704..57de7e2a 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -3,6 +3,7 @@ import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; +import func from "../../deploy/deploy"; import { deployMockComputationModuleFixture } from "../mocks/MockComputationModule.fixture"; import type { Signers } from "../types"; import { deployEnclaveFixture } from "./Enclave.fixture"; @@ -34,19 +35,13 @@ describe("Enclave", function () { this.mockComputationModule_address = mockComputationModule_address; }); - describe("Deployment", function () { - it("correctly sets max duration", async function () { - const maxDuration = await this.enclave.maxDuration(); - - expect(maxDuration).to.equal(this.maxDuration); - }); - + describe("constructor / initialize()", function () { it("correctly sets owner", async function () { // uses the fixture deployment with this.owner set as the owner const owner1 = await this.enclave.owner(); // create a new deployment with this.otherAccount as the owner // note that this.owner is msg.sender in both cases - const enclave = await this.Enclave.deploy(this.otherAccount.address, this.maxDuration); + const enclave = await this.Enclave.deploy(this.otherAccount.address, this.otherAccount.address, this.maxDuration); const owner2 = await enclave.owner(); // expect the owner to be the same as the one set in the fixture @@ -54,19 +49,206 @@ describe("Enclave", function () { // expect the owner to be the same as the one set in the new deployment expect(owner2).to.equal(this.otherAccount); }); + + it("correctly sets cypherNodeRegistry address", async function () { + const cypherNodeRegistry = await this.enclave.cypherNodeRegistry(); + + expect(cypherNodeRegistry).to.equal(this.otherAccount.address); + }); + + it("correctly sets max duration", async function () { + const maxDuration = await this.enclave.maxDuration(); + + expect(maxDuration).to.equal(this.maxDuration); + }); }); describe("setMaxDuration()", function () { - it("reverts if not called by owner"); - it("reverts if duration is 0"); - it("reverts if duration is greater than 30 days"); - it("set max duration correctly"); - it("returns true if max duration is set successfully"); - it("emits MaxDurationChanged event"); + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).setMaxDuration(1)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount.address); + }); + it("set max duration correctly", async function () { + await this.enclave.setMaxDuration(1); + + const maxDuration = await this.enclave.maxDuration(); + expect(maxDuration).to.equal(1); + }); + it("returns true if max duration is set successfully", async function () { + const result = await this.enclave.setMaxDuration.staticCall(1); + + expect(result).to.be.true; + }); + it("emits MaxDurationSet event", async function () { + await expect(this.enclave.setMaxDuration(1)).to.emit(this.enclave, "MaxDurationSet").withArgs(1); + }); + }); + + describe("setCypherNodeRegistry()", function () { + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).setCypherNodeRegistry(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount.address); + }); + it("reverts if given address(0)", async function () { + await expect(this.enclave.setCypherNodeRegistry(ethers.ZeroAddress)) + .to.be.revertedWithCustomError(this.enclave, "InvalidCypherNodeRegistry") + .withArgs(ethers.ZeroAddress); + }); + it("reverts if given address is the same as the current cypherNodeRegistry", async function () { + await expect(this.enclave.setCypherNodeRegistry(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "InvalidCypherNodeRegistry") + .withArgs(this.otherAccount.address); + }); + it("sets cypherNodeRegistry correctly", async function () { + await this.enclave.setCypherNodeRegistry(this.owner.address); + + const cypherNodeRegistry = await this.enclave.cypherNodeRegistry(); + expect(cypherNodeRegistry).to.equal(this.owner.address); + }); + it("returns true if cypherNodeRegistry is set successfully", async function () { + const result = await this.enclave.setCypherNodeRegistry.staticCall(this.owner.address); + + expect(result).to.be.true; + }); + it("emits CypherNodeRegistrySet event", async function () { + await expect(this.enclave.setCypherNodeRegistry(this.owner.address)) + .to.emit(this.enclave, "CypherNodeRegistrySet") + .withArgs(this.owner.address); + }); }); - describe("getE3Id()", function () { - it("reverts if E3 does not exist"); + describe("getE3()", function () { + it("reverts if E3 does not exist", async function () { + await expect(this.enclave.getE3(1)).to.be.revertedWithCustomError(this.enclave, "E3DoesNotExist").withArgs(1); + }); it("returns correct E3 details"); }); + + describe("enableComputationModule()", function () { + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).enableComputationModule(this.mockComputationModule_address)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount); + }); + it("reverts if computation module is already enabled", async function () { + await this.enclave.enableComputationModule(this.mockComputationModule_address); + + await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) + .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") + .withArgs(this.mockComputationModule_address); + }); + it("enables computation module correctly", async function () { + await this.enclave.enableComputationModule(this.mockComputationModule_address); + + const enabled = await this.enclave.computationModules(this.mockComputationModule_address); + expect(enabled).to.be.true; + }); + it("returns true if computation module is enabled successfully", async function () { + const result = await this.enclave.enableComputationModule.staticCall(this.mockComputationModule_address); + + expect(result).to.be.true; + }); + it("emits ComputationModuleEnabled event", async function () { + await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) + .to.emit(this.enclave, "ComputationModuleEnabled") + .withArgs(this.mockComputationModule_address); + }); + }); + + describe("disableComputationModule()", function () { + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).disableComputationModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount.address); + }); + it("reverts if computation module is not enabled", async function () { + await expect(this.enclave.disableComputationModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + .withArgs(this.otherAccount.address); + }); + it("disables computation module correctly", async function () { + await this.enclave.enableComputationModule(this.otherAccount.address); + await this.enclave.disableComputationModule(this.otherAccount.address); + + const enabled = await this.enclave.computationModules(this.otherAccount.address); + expect(enabled).to.be.false; + }); + it("returns true if computation module is disabled successfully", async function () { + await this.enclave.enableComputationModule(this.otherAccount.address); + const result = await this.enclave.disableComputationModule.staticCall(this.otherAccount.address); + + expect(result).to.be.true; + }); + it("emits ComputationModuleDisabled event", async function () { + await this.enclave.enableComputationModule(this.otherAccount.address); + await expect(this.enclave.disableComputationModule(this.otherAccount.address)) + .to.emit(this.enclave, "ComputationModuleDisabled") + .withArgs(this.otherAccount.address); + }); + }); + + describe("enableExecutionModule()", function () { + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).enableExecutionModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount.address); + }); + it("reverts if execution module is already enabled", async function () { + await this.enclave.enableExecutionModule(this.otherAccount.address); + + await expect(this.enclave.enableExecutionModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") + .withArgs(this.otherAccount.address); + }); + it("enables execution module correctly", async function () { + await this.enclave.enableExecutionModule(this.otherAccount.address); + + const enabled = await this.enclave.executionModules(this.otherAccount.address); + expect(enabled).to.be.true; + }); + it("returns true if execution module is enabled successfully", async function () { + const result = await this.enclave.enableExecutionModule.staticCall(this.otherAccount.address); + + expect(result).to.be.true; + }); + it("emits ExecutionModuleEnabled event", async function () { + await expect(this.enclave.enableExecutionModule(this.otherAccount.address)) + .to.emit(this.enclave, "ExecutionModuleEnabled") + .withArgs(this.otherAccount.address); + }); + }); + + describe("disableExecutionModule()", function () { + it("reverts if not called by owner", async function () { + await expect(this.enclave.connect(this.otherAccount).disableExecutionModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + .withArgs(this.otherAccount.address); + }); + it("reverts if execution module is not enabled", async function () { + await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) + .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + .withArgs(this.otherAccount.address); + }); + it("disables execution module correctly", async function () { + await this.enclave.enableExecutionModule(this.otherAccount.address); + await this.enclave.disableExecutionModule(this.otherAccount.address); + + const enabled = await this.enclave.executionModules(this.otherAccount.address); + expect(enabled).to.be.false; + }); + it("returns true if execution module is disabled successfully", async function () { + await this.enclave.enableExecutionModule(this.otherAccount.address); + const result = await this.enclave.disableExecutionModule.staticCall(this.otherAccount.address); + + expect(result).to.be.true; + }); + it("emits ExecutionModuleDisabled event", async function () { + await this.enclave.enableExecutionModule(this.otherAccount.address); + await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) + .to.emit(this.enclave, "ExecutionModuleDisabled") + .withArgs(this.otherAccount.address); + }); + }); }); From 6097f289171629fb1df2926b5ca5e989bae5563d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 31 May 2024 16:31:18 +1000 Subject: [PATCH 26/62] add mock fixtures --- packages/evm/test/encalve/Enclave.spec.ts | 24 +++++++++++++++++++ .../mocks/MockComputationModule.fixture.ts | 5 +--- .../mocks/MockCypherNodeRegistry.fixture.ts | 13 ++++++++++ .../test/mocks/MockExecutionModule.fixture.ts | 11 +++++++++ .../test/mocks/MockInputValidator.fixture.ts | 11 +++++++++ .../test/mocks/MockOutputVerifier.fixture.ts | 11 +++++++++ 6 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts create mode 100644 packages/evm/test/mocks/MockExecutionModule.fixture.ts create mode 100644 packages/evm/test/mocks/MockInputValidator.fixture.ts create mode 100644 packages/evm/test/mocks/MockOutputVerifier.fixture.ts diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 57de7e2a..db84c07f 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -5,6 +5,10 @@ import { ethers } from "hardhat"; import func from "../../deploy/deploy"; import { deployMockComputationModuleFixture } from "../mocks/MockComputationModule.fixture"; +import { deployMockCypherNodeRegistryFixture } from "../mocks/MockCypherNodeRegistry.fixture"; +import { deployMockExecutionModuleFixture } from "../mocks/MockExecutionModule.fixture"; +import { deployMockInputValidatorFixture } from "../mocks/MockInputValidator.fixture"; +import { deployMockOutputVerifierFixture } from "../mocks/MockOutputVerifier.fixture"; import type { Signers } from "../types"; import { deployEnclaveFixture } from "./Enclave.fixture"; @@ -33,6 +37,26 @@ describe("Enclave", function () { ); this.mockComputationModule = mockComputationModule; this.mockComputationModule_address = mockComputationModule_address; + + const { mockOutputVerifier, mockOutputVerifier_address } = await this.loadFixture(deployMockOutputVerifierFixture); + this.mockOutputVerifier = mockOutputVerifier; + this.mockOutputVerifier_address = mockOutputVerifier_address; + + const { mockCypherNodeRegistry, mockCypherNodeRegistry_address } = await this.loadFixture( + deployMockCypherNodeRegistryFixture, + ); + this.mockCypherNodeRegistry = mockCypherNodeRegistry; + this.mockCypherNodeRegistry_address = mockCypherNodeRegistry_address; + + const { mockExecutionModule, mockExecutionModule_address } = await this.loadFixture( + deployMockExecutionModuleFixture, + ); + this.mockExecutionModule = mockExecutionModule; + this.mockExecutionModule_address = mockExecutionModule_address; + + const { mockInputValidator, mockInputValidator_address } = await this.loadFixture(deployMockInputValidatorFixture); + this.mockInputValidator = mockInputValidator; + this.mockInputValidator_address = mockInputValidator_address; }); describe("constructor / initialize()", function () { diff --git a/packages/evm/test/mocks/MockComputationModule.fixture.ts b/packages/evm/test/mocks/MockComputationModule.fixture.ts index 3d6f6c41..3610de33 100644 --- a/packages/evm/test/mocks/MockComputationModule.fixture.ts +++ b/packages/evm/test/mocks/MockComputationModule.fixture.ts @@ -4,14 +4,11 @@ import type { MockComputationModule } from "../../types/contracts/test/MockCompu import type { MockComputationModule__factory } from "../../types/factories/contracts/test/MockComputationModule__factory"; export async function deployMockComputationModuleFixture() { - // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await ethers.getSigners(); - const MockComputationModule = (await ethers.getContractFactory( "MockComputationModule", )) as MockComputationModule__factory; const mockComputationModule = (await MockComputationModule.deploy()) as MockComputationModule; const mockComputationModule_address = await mockComputationModule.getAddress(); - return { mockComputationModule, mockComputationModule_address, owner, otherAccount }; + return { mockComputationModule, mockComputationModule_address }; } diff --git a/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts new file mode 100644 index 00000000..90aaffac --- /dev/null +++ b/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts @@ -0,0 +1,13 @@ +import { ethers } from "hardhat"; + +import { MockCypherNodeRegistry } from "../../types/contracts/test/MockCypherNodeRegistry"; +import { MockCypherNodeRegistry__factory } from "../../types/factories/contracts/test/MockCypherNodeRegistry__factory"; + +export async function deployMockCypherNodeRegistryFixture() { + const MockCypherNodeRegistry = (await ethers.getContractFactory( + "MockCypherNodeRegistry", + )) as MockCypherNodeRegistry__factory; + const mockCypherNodeRegistry = (await MockCypherNodeRegistry.deploy()) as MockCypherNodeRegistry; + const mockCypherNodeRegistry_address = mockCypherNodeRegistry.getAddress(); + return { mockCypherNodeRegistry, mockCypherNodeRegistry_address }; +} diff --git a/packages/evm/test/mocks/MockExecutionModule.fixture.ts b/packages/evm/test/mocks/MockExecutionModule.fixture.ts new file mode 100644 index 00000000..b2a897e4 --- /dev/null +++ b/packages/evm/test/mocks/MockExecutionModule.fixture.ts @@ -0,0 +1,11 @@ +import { ethers } from "hardhat"; + +import { MockExecutionModule } from "../../types/contracts/test/MockExecutionModule"; +import { MockExecutionModule__factory } from "../../types/factories/contracts/test/MockExecutionModule__factory"; + +export async function deployMockExecutionModuleFixture() { + const MockExecutionModule = (await ethers.getContractFactory("MockExecutionModule")) as MockExecutionModule__factory; + const mockExecutionModule = (await MockExecutionModule.deploy()) as MockExecutionModule; + const mockExecutionModule_address = mockExecutionModule.getAddress(); + return { mockExecutionModule, mockExecutionModule_address }; +} diff --git a/packages/evm/test/mocks/MockInputValidator.fixture.ts b/packages/evm/test/mocks/MockInputValidator.fixture.ts new file mode 100644 index 00000000..0e7ed047 --- /dev/null +++ b/packages/evm/test/mocks/MockInputValidator.fixture.ts @@ -0,0 +1,11 @@ +import { ethers } from "hardhat"; + +import { MockInputValidator } from "../../types/contracts/test/MockInputValidator"; +import { MockInputValidator__factory } from "../../types/factories/contracts/test/MockInputValidator__factory"; + +export async function deployMockInputValidatorFixture() { + const MockInputValidator = (await ethers.getContractFactory("MockInputValidator")) as MockInputValidator__factory; + const mockInputValidator = (await MockInputValidator.deploy()) as MockInputValidator; + const mockInputValidator_address = mockInputValidator.getAddress(); + return { mockInputValidator, mockInputValidator_address }; +} diff --git a/packages/evm/test/mocks/MockOutputVerifier.fixture.ts b/packages/evm/test/mocks/MockOutputVerifier.fixture.ts new file mode 100644 index 00000000..52553df4 --- /dev/null +++ b/packages/evm/test/mocks/MockOutputVerifier.fixture.ts @@ -0,0 +1,11 @@ +import { ethers } from "hardhat"; + +import { MockOutputVerifier } from "../../types/contracts/test/MockOutputVerifier"; +import { MockOutputVerifier__factory } from "../../types/factories/contracts/test/MockOutputVerifier__factory"; + +export async function deployMockOutputVerifierFixture() { + const MockOutputVerifier = (await ethers.getContractFactory("MockOutputVerifier")) as MockOutputVerifier__factory; + const mockOutputVerifier = (await MockOutputVerifier.deploy()) as MockOutputVerifier; + const mockOutputVerifier_address = mockOutputVerifier.getAddress(); + return { mockOutputVerifier, mockOutputVerifier_address }; +} From 9b7d07529c00086a34f8dd5ab3ec0df2d0a06243 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 31 May 2024 20:48:53 +1000 Subject: [PATCH 27/62] use mocks instead of otherAccount --- packages/evm/test/encalve/Enclave.spec.ts | 62 +++++++++++------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index db84c07f..1ce21bca 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -183,96 +183,96 @@ describe("Enclave", function () { describe("disableComputationModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).disableComputationModule(this.otherAccount.address)) + await expect(this.enclave.connect(this.otherAccount).disableComputationModule(this.mockComputationModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") .withArgs(this.otherAccount.address); }); it("reverts if computation module is not enabled", async function () { - await expect(this.enclave.disableComputationModule(this.otherAccount.address)) + await expect(this.enclave.disableComputationModule(this.mockComputationModule_address)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockComputationModule_address); }); it("disables computation module correctly", async function () { - await this.enclave.enableComputationModule(this.otherAccount.address); - await this.enclave.disableComputationModule(this.otherAccount.address); + await this.enclave.enableComputationModule(this.mockComputationModule_address); + await this.enclave.disableComputationModule(this.mockComputationModule_address); - const enabled = await this.enclave.computationModules(this.otherAccount.address); + const enabled = await this.enclave.computationModules(this.mockComputationModule_address); expect(enabled).to.be.false; }); it("returns true if computation module is disabled successfully", async function () { - await this.enclave.enableComputationModule(this.otherAccount.address); - const result = await this.enclave.disableComputationModule.staticCall(this.otherAccount.address); + await this.enclave.enableComputationModule(this.mockComputationModule_address); + const result = await this.enclave.disableComputationModule.staticCall(this.mockComputationModule_address); expect(result).to.be.true; }); it("emits ComputationModuleDisabled event", async function () { - await this.enclave.enableComputationModule(this.otherAccount.address); - await expect(this.enclave.disableComputationModule(this.otherAccount.address)) + await this.enclave.enableComputationModule(this.mockComputationModule_address); + await expect(this.enclave.disableComputationModule(this.mockComputationModule_address)) .to.emit(this.enclave, "ComputationModuleDisabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockComputationModule_address); }); }); describe("enableExecutionModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).enableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.connect(this.otherAccount).enableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") .withArgs(this.otherAccount.address); }); it("reverts if execution module is already enabled", async function () { - await this.enclave.enableExecutionModule(this.otherAccount.address); + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); - await expect(this.enclave.enableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockExecutionModule_address); }); it("enables execution module correctly", async function () { - await this.enclave.enableExecutionModule(this.otherAccount.address); + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); - const enabled = await this.enclave.executionModules(this.otherAccount.address); + const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); expect(enabled).to.be.true; }); it("returns true if execution module is enabled successfully", async function () { - const result = await this.enclave.enableExecutionModule.staticCall(this.otherAccount.address); + const result = await this.enclave.enableExecutionModule.staticCall(this.mockExecutionModule_address); expect(result).to.be.true; }); it("emits ExecutionModuleEnabled event", async function () { - await expect(this.enclave.enableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) .to.emit(this.enclave, "ExecutionModuleEnabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockExecutionModule_address); }); }); describe("disableExecutionModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).disableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.connect(this.otherAccount).disableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") .withArgs(this.otherAccount.address); }); it("reverts if execution module is not enabled", async function () { - await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.disableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockExecutionModule_address); }); it("disables execution module correctly", async function () { - await this.enclave.enableExecutionModule(this.otherAccount.address); - await this.enclave.disableExecutionModule(this.otherAccount.address); + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); + await this.enclave.disableExecutionModule(this.mockExecutionModule_address); - const enabled = await this.enclave.executionModules(this.otherAccount.address); + const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); expect(enabled).to.be.false; }); it("returns true if execution module is disabled successfully", async function () { - await this.enclave.enableExecutionModule(this.otherAccount.address); - const result = await this.enclave.disableExecutionModule.staticCall(this.otherAccount.address); + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); + const result = await this.enclave.disableExecutionModule.staticCall(this.mockExecutionModule_address); expect(result).to.be.true; }); it("emits ExecutionModuleDisabled event", async function () { - await this.enclave.enableExecutionModule(this.otherAccount.address); - await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); + await expect(this.enclave.disableExecutionModule(this.mockExecutionModule_address)) .to.emit(this.enclave, "ExecutionModuleDisabled") - .withArgs(this.otherAccount.address); + .withArgs(this.mockExecutionModule_address); }); }); }); From bb5342fe0975513604d41c41ad211f9f3259d254 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 31 May 2024 21:11:26 +1000 Subject: [PATCH 28/62] await promise on getAddress --- packages/evm/test/encalve/Enclave.spec.ts | 8 +++++--- packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts | 3 ++- packages/evm/test/mocks/MockExecutionModule.fixture.ts | 3 ++- packages/evm/test/mocks/MockInputValidator.fixture.ts | 3 ++- packages/evm/test/mocks/MockOutputVerifier.fixture.ts | 3 ++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 1ce21bca..f909b482 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -57,6 +57,8 @@ describe("Enclave", function () { const { mockInputValidator, mockInputValidator_address } = await this.loadFixture(deployMockInputValidatorFixture); this.mockInputValidator = mockInputValidator; this.mockInputValidator_address = mockInputValidator_address; + + await this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address); }); describe("constructor / initialize()", function () { @@ -77,7 +79,7 @@ describe("Enclave", function () { it("correctly sets cypherNodeRegistry address", async function () { const cypherNodeRegistry = await this.enclave.cypherNodeRegistry(); - expect(cypherNodeRegistry).to.equal(this.otherAccount.address); + expect(cypherNodeRegistry).to.equal(this.mockCypherNodeRegistry_address); }); it("correctly sets max duration", async function () { @@ -121,9 +123,9 @@ describe("Enclave", function () { .withArgs(ethers.ZeroAddress); }); it("reverts if given address is the same as the current cypherNodeRegistry", async function () { - await expect(this.enclave.setCypherNodeRegistry(this.otherAccount.address)) + await expect(this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address)) .to.be.revertedWithCustomError(this.enclave, "InvalidCypherNodeRegistry") - .withArgs(this.otherAccount.address); + .withArgs(this.mockCypherNodeRegistry_address); }); it("sets cypherNodeRegistry correctly", async function () { await this.enclave.setCypherNodeRegistry(this.owner.address); diff --git a/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts index 90aaffac..89d710ba 100644 --- a/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts +++ b/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts @@ -8,6 +8,7 @@ export async function deployMockCypherNodeRegistryFixture() { "MockCypherNodeRegistry", )) as MockCypherNodeRegistry__factory; const mockCypherNodeRegistry = (await MockCypherNodeRegistry.deploy()) as MockCypherNodeRegistry; - const mockCypherNodeRegistry_address = mockCypherNodeRegistry.getAddress(); + const mockCypherNodeRegistry_address = await mockCypherNodeRegistry.getAddress(); + return { mockCypherNodeRegistry, mockCypherNodeRegistry_address }; } diff --git a/packages/evm/test/mocks/MockExecutionModule.fixture.ts b/packages/evm/test/mocks/MockExecutionModule.fixture.ts index b2a897e4..267f3316 100644 --- a/packages/evm/test/mocks/MockExecutionModule.fixture.ts +++ b/packages/evm/test/mocks/MockExecutionModule.fixture.ts @@ -6,6 +6,7 @@ import { MockExecutionModule__factory } from "../../types/factories/contracts/te export async function deployMockExecutionModuleFixture() { const MockExecutionModule = (await ethers.getContractFactory("MockExecutionModule")) as MockExecutionModule__factory; const mockExecutionModule = (await MockExecutionModule.deploy()) as MockExecutionModule; - const mockExecutionModule_address = mockExecutionModule.getAddress(); + const mockExecutionModule_address = await mockExecutionModule.getAddress(); + return { mockExecutionModule, mockExecutionModule_address }; } diff --git a/packages/evm/test/mocks/MockInputValidator.fixture.ts b/packages/evm/test/mocks/MockInputValidator.fixture.ts index 0e7ed047..096c86f1 100644 --- a/packages/evm/test/mocks/MockInputValidator.fixture.ts +++ b/packages/evm/test/mocks/MockInputValidator.fixture.ts @@ -6,6 +6,7 @@ import { MockInputValidator__factory } from "../../types/factories/contracts/tes export async function deployMockInputValidatorFixture() { const MockInputValidator = (await ethers.getContractFactory("MockInputValidator")) as MockInputValidator__factory; const mockInputValidator = (await MockInputValidator.deploy()) as MockInputValidator; - const mockInputValidator_address = mockInputValidator.getAddress(); + const mockInputValidator_address = await mockInputValidator.getAddress(); + return { mockInputValidator, mockInputValidator_address }; } diff --git a/packages/evm/test/mocks/MockOutputVerifier.fixture.ts b/packages/evm/test/mocks/MockOutputVerifier.fixture.ts index 52553df4..a0615819 100644 --- a/packages/evm/test/mocks/MockOutputVerifier.fixture.ts +++ b/packages/evm/test/mocks/MockOutputVerifier.fixture.ts @@ -6,6 +6,7 @@ import { MockOutputVerifier__factory } from "../../types/factories/contracts/tes export async function deployMockOutputVerifierFixture() { const MockOutputVerifier = (await ethers.getContractFactory("MockOutputVerifier")) as MockOutputVerifier__factory; const mockOutputVerifier = (await MockOutputVerifier.deploy()) as MockOutputVerifier; - const mockOutputVerifier_address = mockOutputVerifier.getAddress(); + const mockOutputVerifier_address = await mockOutputVerifier.getAddress(); + return { mockOutputVerifier, mockOutputVerifier_address }; } From 8c8eaab8a6c4b5b7077edf2e7a3711a7a6ef1f2d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 3 Jun 2024 14:05:20 +1000 Subject: [PATCH 29/62] add unit tests for Enclave.request() --- packages/evm/contracts/Enclave.sol | 20 +- .../contracts/test/MockComputationModule.sol | 9 +- .../contracts/test/MockExecutionModule.sol | 8 +- packages/evm/test/encalve/Enclave.spec.ts | 239 ++++++++++++++++-- 4 files changed, 240 insertions(+), 36 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 2b82f7f8..ff56b9b5 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -38,7 +38,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// error CommitteeSelectionFailed(); - error ComputationModuleNotAllowed(); + error ComputationModuleNotAllowed(IComputationModule computationModule); error E3AlreadyActivated(uint256 e3Id); error E3DoesNotExist(uint256 e3Id); error ModuleAlreadyEnabled(address module); @@ -49,12 +49,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { error InvalidExecutionModuleSetup(); error InvalidCypherNodeRegistry(ICypherNodeRegistry cypherNodeRegistry); error InvalidInput(); - error InvalidDuration(); + error InvalidDuration(uint256 duration); error InvalidOutput(); - error InvalidThreshold(); + error InvalidThreshold(uint32[2] threshold); error CiphertextOutputAlreadyPublished(uint256 e3Id); error CiphertextOutputNotPublished(uint256 e3Id); - error PaymentRequired(); + error PaymentRequired(uint256 value); error PlaintextOutputAlreadyPublished(uint256 e3Id); //////////////////////////////////////////////////////////// @@ -97,11 +97,13 @@ contract Enclave is IEnclave, OwnableUpgradeable { IExecutionModule executionModule, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3) { - require(msg.value > 0, PaymentRequired()); // TODO: allow for other payment methods or only native tokens? + // TODO: allow for other payment methods or only native tokens? + // TODO: should payment checks be done somewhere else? Perhaps in the computation module or cypher node registry? + require(msg.value > 0, PaymentRequired(msg.value)); - require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold()); - require(duration > 0 && duration <= maxDuration, InvalidDuration()); - require(computationModules[computationModule], ComputationModuleNotAllowed()); + require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold(threshold)); + require(duration > 0 && duration <= maxDuration, InvalidDuration(duration)); // TODO: should 0 be a magic number for infinite duration? + require(computationModules[computationModule], ComputationModuleNotAllowed(computationModule)); require(executionModules[executionModule], ModuleNotEnabled(address(executionModule))); // TODO: should IDs be incremental or produced deterministic? @@ -137,7 +139,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { function activate(uint256 e3Id) external returns (bool success) { E3 storage e3 = e3s[e3Id]; require(e3.expiration == 0, E3AlreadyActivated(e3Id)); - e3.expiration = block.timestamp + maxDuration; + e3.expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. e3.committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); success = e3.committeePublicKey.length > 0; diff --git a/packages/evm/contracts/test/MockComputationModule.sol b/packages/evm/contracts/test/MockComputationModule.sol index a7220bdf..e7ffe424 100644 --- a/packages/evm/contracts/test/MockComputationModule.sol +++ b/packages/evm/contracts/test/MockComputationModule.sol @@ -4,8 +4,13 @@ pragma solidity >=0.8.26; import { IComputationModule, IInputValidator } from "../interfaces/IComputationModule.sol"; contract MockComputationModule is IComputationModule { - function validate(bytes calldata params) external pure returns (IInputValidator inputValidator) { - (inputValidator) = abi.decode(params, (IInputValidator)); + error invalidParams(bytes params); + + function validate(bytes memory params) external pure returns (IInputValidator inputValidator) { + require(params.length == 32, "invalid params"); + assembly { + inputValidator := mload(add(params, 32)) + } } function verify(uint256, bytes memory outputData) external pure returns (bytes memory output, bool success) { diff --git a/packages/evm/contracts/test/MockExecutionModule.sol b/packages/evm/contracts/test/MockExecutionModule.sol index 93beb81b..a381cb5c 100644 --- a/packages/evm/contracts/test/MockExecutionModule.sol +++ b/packages/evm/contracts/test/MockExecutionModule.sol @@ -4,7 +4,13 @@ pragma solidity >=0.8.26; import { IExecutionModule, IOutputVerifier } from "../interfaces/IExecutionModule.sol"; contract MockExecutionModule is IExecutionModule { - function validate(bytes calldata params) external pure returns (IOutputVerifier outputVerifier) { + error invalidParams(); + + function validate(bytes memory params) external pure returns (IOutputVerifier outputVerifier) { + require(params.length == 32, invalidParams()); + assembly { + outputVerifier := mload(add(params, 32)) + } (outputVerifier) = abi.decode(params, (IOutputVerifier)); } } diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index f909b482..03d808ea 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -1,6 +1,7 @@ import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; +import exp from "constants"; import { ethers } from "hardhat"; import func from "../../deploy/deploy"; @@ -12,6 +13,8 @@ import { deployMockOutputVerifierFixture } from "../mocks/MockOutputVerifier.fix import type { Signers } from "../types"; import { deployEnclaveFixture } from "./Enclave.fixture"; +const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + describe("Enclave", function () { before(async function () { this.signers = {} as Signers; @@ -59,6 +62,18 @@ describe("Enclave", function () { this.mockInputValidator_address = mockInputValidator_address; await this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address); + await this.enclave.enableComputationModule(this.mockComputationModule_address); + await this.enclave.enableExecutionModule(this.mockExecutionModule_address); + + this.requestParams = { + poolId: 1n, + threshold: [2n, 2n], + duration: time.duration.days(30), + computationModule: this.mockComputationModule_address, + cMParams: abiCoder.encode(["address"], [this.mockInputValidator_address]), + executionModule: this.mockExecutionModule_address, + eMParams: abiCoder.encode(["address"], [this.mockOutputVerifier_address]), + }; }); describe("constructor / initialize()", function () { @@ -159,27 +174,23 @@ describe("Enclave", function () { .withArgs(this.otherAccount); }); it("reverts if computation module is already enabled", async function () { - await this.enclave.enableComputationModule(this.mockComputationModule_address); - await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") .withArgs(this.mockComputationModule_address); }); it("enables computation module correctly", async function () { - await this.enclave.enableComputationModule(this.mockComputationModule_address); - const enabled = await this.enclave.computationModules(this.mockComputationModule_address); expect(enabled).to.be.true; }); it("returns true if computation module is enabled successfully", async function () { - const result = await this.enclave.enableComputationModule.staticCall(this.mockComputationModule_address); + const result = await this.enclave.enableComputationModule.staticCall(this.otherAccount.address); expect(result).to.be.true; }); it("emits ComputationModuleEnabled event", async function () { - await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) + await expect(this.enclave.enableComputationModule(this.otherAccount.address)) .to.emit(this.enclave, "ComputationModuleEnabled") - .withArgs(this.mockComputationModule_address); + .withArgs(this.otherAccount.address); }); }); @@ -190,25 +201,22 @@ describe("Enclave", function () { .withArgs(this.otherAccount.address); }); it("reverts if computation module is not enabled", async function () { - await expect(this.enclave.disableComputationModule(this.mockComputationModule_address)) + await expect(this.enclave.disableComputationModule(this.otherAccount.address)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.mockComputationModule_address); + .withArgs(this.otherAccount.address); }); it("disables computation module correctly", async function () { - await this.enclave.enableComputationModule(this.mockComputationModule_address); await this.enclave.disableComputationModule(this.mockComputationModule_address); const enabled = await this.enclave.computationModules(this.mockComputationModule_address); expect(enabled).to.be.false; }); it("returns true if computation module is disabled successfully", async function () { - await this.enclave.enableComputationModule(this.mockComputationModule_address); const result = await this.enclave.disableComputationModule.staticCall(this.mockComputationModule_address); expect(result).to.be.true; }); it("emits ComputationModuleDisabled event", async function () { - await this.enclave.enableComputationModule(this.mockComputationModule_address); await expect(this.enclave.disableComputationModule(this.mockComputationModule_address)) .to.emit(this.enclave, "ComputationModuleDisabled") .withArgs(this.mockComputationModule_address); @@ -222,27 +230,23 @@ describe("Enclave", function () { .withArgs(this.otherAccount.address); }); it("reverts if execution module is already enabled", async function () { - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); - await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") .withArgs(this.mockExecutionModule_address); }); it("enables execution module correctly", async function () { - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); - const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); expect(enabled).to.be.true; }); it("returns true if execution module is enabled successfully", async function () { - const result = await this.enclave.enableExecutionModule.staticCall(this.mockExecutionModule_address); + const result = await this.enclave.enableExecutionModule.staticCall(this.otherAccount.address); expect(result).to.be.true; }); it("emits ExecutionModuleEnabled event", async function () { - await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) + await expect(this.enclave.enableExecutionModule(this.otherAccount)) .to.emit(this.enclave, "ExecutionModuleEnabled") - .withArgs(this.mockExecutionModule_address); + .withArgs(this.otherAccount); }); }); @@ -253,28 +257,215 @@ describe("Enclave", function () { .withArgs(this.otherAccount.address); }); it("reverts if execution module is not enabled", async function () { - await expect(this.enclave.disableExecutionModule(this.mockExecutionModule_address)) + await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.mockExecutionModule_address); + .withArgs(this.otherAccount.address); }); it("disables execution module correctly", async function () { - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); await this.enclave.disableExecutionModule(this.mockExecutionModule_address); const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); expect(enabled).to.be.false; }); it("returns true if execution module is disabled successfully", async function () { - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); const result = await this.enclave.disableExecutionModule.staticCall(this.mockExecutionModule_address); expect(result).to.be.true; }); it("emits ExecutionModuleDisabled event", async function () { - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); await expect(this.enclave.disableExecutionModule(this.mockExecutionModule_address)) .to.emit(this.enclave, "ExecutionModuleDisabled") .withArgs(this.mockExecutionModule_address); }); }); + + describe("request()", function () { + it("reverts if msg.value is 0", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + ), + ).to.be.revertedWithCustomError(this.enclave, "PaymentRequired"); + }); + it("reverts if threshold is 0", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + [0, 2], + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidThreshold"); + }); + it("reverts if threshold is greater than number", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + [3, 2], + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidThreshold"); + }); + it("reverts if duration is 0", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + 0, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidDuration"); + }); + it("reverts if duration is greater than maxDuration", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + time.duration.days(31), + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidDuration"); + }); + it("reverts if computation module is not enabled", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + ethers.ZeroAddress, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ) + .to.be.revertedWithCustomError(this.enclave, "ComputationModuleNotAllowed") + .withArgs(ethers.ZeroAddress); + }); + it("reverts if execution module is not enabled", async function () { + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + ethers.ZeroAddress, + this.requestParams.eMParams, + { value: 10 }, + ), + ) + .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + .withArgs(ethers.ZeroAddress); + }); + it("reverts if input computation module does not return input validator address", async function () { + const zeroInput = abiCoder.encode(["address"], [ethers.ZeroAddress]); + + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + zeroInput, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidComputation"); + }); + it("reverts if input execution module does not return output verifier address", async function () { + const zeroInput = abiCoder.encode(["address"], [ethers.ZeroAddress]); + + await expect( + this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + zeroInput, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "InvalidExecutionModuleSetup"); + }); + it("reverts if committee selection fails", async function () { + await expect( + this.enclave.request( + 0, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ), + ).to.be.revertedWithCustomError(this.enclave, "CommitteeSelectionFailed"); + }); + it("instantiates a new E3", async function () { + await this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ); + const e3 = await this.enclave.getE3(0); + + expect(e3.threshold).to.deep.equal(this.requestParams.threshold); + expect(e3.expiration).to.equal(0n); + expect(e3.computationModule).to.equal(this.requestParams.computationModule); + expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], this.requestParams.cMParams)[0]); + expect(e3.executionModule).to.equal(this.requestParams.executionModule); + expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], this.requestParams.eMParams)[0]); + expect(e3.committeePublicKey).to.equal("0x"); + expect(e3.ciphertextOutput).to.equal("0x"); + expect(e3.plaintextOutput).to.equal("0x"); + }); + it("emits E3Requested event", async function () { + const tx = await this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ); + const e3 = await this.enclave.getE3(0); + + await expect(tx) + .to.emit(this.enclave, "E3Requested") + .withArgs(0, e3, 1, this.requestParams.computationModule, this.requestParams.executionModule); + }); + }); }); From 27c1b58af576f2f370294c4a441dbdf81ff8ce2b Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 3 Jun 2024 14:08:00 +1000 Subject: [PATCH 30/62] add unit test for getE3() --- packages/evm/test/encalve/Enclave.spec.ts | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index 03d808ea..c58be52b 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -164,7 +164,29 @@ describe("Enclave", function () { it("reverts if E3 does not exist", async function () { await expect(this.enclave.getE3(1)).to.be.revertedWithCustomError(this.enclave, "E3DoesNotExist").withArgs(1); }); - it("returns correct E3 details"); + it("returns correct E3 details", async function () { + await this.enclave.request( + this.requestParams.poolId, + this.requestParams.threshold, + this.requestParams.duration, + this.requestParams.computationModule, + this.requestParams.cMParams, + this.requestParams.executionModule, + this.requestParams.eMParams, + { value: 10 }, + ); + const e3 = await this.enclave.getE3(0); + + expect(e3.threshold).to.deep.equal(this.requestParams.threshold); + expect(e3.expiration).to.equal(0n); + expect(e3.computationModule).to.equal(this.requestParams.computationModule); + expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], this.requestParams.cMParams)[0]); + expect(e3.executionModule).to.equal(this.requestParams.executionModule); + expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], this.requestParams.eMParams)[0]); + expect(e3.committeePublicKey).to.equal("0x"); + expect(e3.ciphertextOutput).to.equal("0x"); + expect(e3.plaintextOutput).to.equal("0x"); + }); }); describe("enableComputationModule()", function () { From 9bc9340c09a643c3366211e386f6d0c66e74e46f Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 3 Jun 2024 14:33:26 +1000 Subject: [PATCH 31/62] add unit test stubs for remaining core functions --- packages/evm/contracts/Enclave.sol | 28 +++++++------ .../evm/contracts/interfaces/IEnclave.sol | 4 +- packages/evm/test/encalve/Enclave.spec.ts | 41 +++++++++++++++++++ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index ff56b9b5..ff877085 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -137,46 +137,48 @@ contract Enclave is IEnclave, OwnableUpgradeable { } function activate(uint256 e3Id) external returns (bool success) { - E3 storage e3 = e3s[e3Id]; + E3 memory e3 = getE3(e3Id); require(e3.expiration == 0, E3AlreadyActivated(e3Id)); e3.expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. - e3.committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); - success = e3.committeePublicKey.length > 0; + bytes memory committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); + success = committeePublicKey.length > 0; require(success, CommitteeSelectionFailed()); + e3s[e3Id].committeePublicKey = committeePublicKey; emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey); } function publishInput(uint256 e3Id, bytes memory data) external returns (bool success) { - E3 storage e3 = e3s[e3Id]; - require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); + E3 memory e3 = getE3(e3Id); + require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); // TODO: should we have an input window, including both a start and end timestamp? bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - + // TODO: do we need to store or accumulate the inputs? Probably yes. emit InputPublished(e3Id, input); } - function publishOutput(uint256 e3Id, bytes memory data) external returns (bool success) { - E3 storage e3 = e3s[e3Id]; + function publishComputationOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + E3 memory e3 = getE3(e3Id); require(e3.expiration <= block.timestamp, InputDeadlineNotPassed(e3Id, e3.expiration)); - require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); + require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); // TODO: should the output verifier be able to change its mind? i.e. should we be able to call this multiple times? bytes memory output; (output, success) = e3.outputVerifier.verify(e3Id, data); require(success, InvalidOutput()); - e3.ciphertextOutput = output; + e3s[e3Id].ciphertextOutput = output; emit CiphertextOutputPublished(e3Id, output); } - function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success) { - E3 storage e3 = e3s[e3Id]; + function publishDecryptionOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + E3 memory e3 = getE3(e3Id); require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); bytes memory output; (output, success) = e3.computationModule.verify(e3Id, data); - e3.plaintextOutput = output; + require(success, InvalidOutput()); + e3s[e3Id].plaintextOutput = output; emit PlaintextOutputPublished(e3Id, output); } diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index ddf8a376..56e364b0 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -116,7 +116,7 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to verify. /// @return success True if the output was successfully published. - function publishOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishComputationOutput(uint256 e3Id, bytes memory data) external returns (bool success); /// @notice This function should be called to decrypt the output of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the output has not been published. @@ -124,7 +124,7 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. - function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishDecryptionOutput(uint256 e3Id, bytes memory data) external returns (bool success); //////////////////////////////////////////////////////////// // // diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index c58be52b..c6a56ad4 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -490,4 +490,45 @@ describe("Enclave", function () { .withArgs(0, e3, 1, this.requestParams.computationModule, this.requestParams.executionModule); }); }); + + describe("activate()", function () { + it("reverts if E3 does not exist"); + it("reverts if E3 has already been activated"); + it("reverts if cypherNodeRegistry does not return a public key"); + it("sets committeePublicKey correctly"); + it("returns true if E3 is activated successfully"); + it("emits E3Activated event"); + }); + + describe("publishInput()", function () { + it("reverts if E3 does not exist"); + it("reverts if E3 has not been activated"); + it("reverts if outside of input window"); + it("reverts if input is not valid"); + it("sets ciphertextInput correctly"); + it("returns true if input is published successfully"); + it("emits InputPublished event"); + }); + + describe("publishComputationOutput()", function () { + it("reverts if E3 does not exist"); + it("reverts if E3 has not been activated"); + it("reverts if input deadline has not passed"); + it("reverts if output has already been published"); + it("reverts if output is not valid"); + it("sets ciphertextOutput correctly"); + it("returns true if output is published successfully"); + it("emits CiphertextOutputPublished event"); + }); + + describe("publishExecutionOutput()", function () { + it("reverts if E3 does not exist"); + it("reverts if E3 has not been activated"); + it("reverts if ciphertextOutput has not been published"); + it("reverts if plaintextOutput has already been published"); + it("reverts if output is not valid"); + it("sets plaintextOutput correctly"); + it("returns true if output is published successfully"); + it("emits PlaintextOutputPublished event"); + }); }); From 2bdadb68b999d1e96939c5d1c31fee965a6fa2cd Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 3 Jun 2024 15:00:18 +1000 Subject: [PATCH 32/62] rename some functions publishComputationOutput --> publishCiphertextOutput publishDecryptionOutput --> publishDecryptedOutput --- packages/evm/contracts/Enclave.sol | 4 ++-- packages/evm/contracts/interfaces/IEnclave.sol | 4 ++-- packages/evm/test/encalve/Enclave.spec.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index ff877085..cf4c1765 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -159,7 +159,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit InputPublished(e3Id, input); } - function publishComputationOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishCiphertextOutput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.expiration <= block.timestamp, InputDeadlineNotPassed(e3Id, e3.expiration)); require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); // TODO: should the output verifier be able to change its mind? i.e. should we be able to call this multiple times? @@ -171,7 +171,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit CiphertextOutputPublished(e3Id, output); } - function publishDecryptionOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 56e364b0..cbcde5a6 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -116,7 +116,7 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to verify. /// @return success True if the output was successfully published. - function publishComputationOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishCiphertextOutput(uint256 e3Id, bytes memory data) external returns (bool success); /// @notice This function should be called to decrypt the output of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the output has not been published. @@ -124,7 +124,7 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. - function publishDecryptionOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success); //////////////////////////////////////////////////////////// // // diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/encalve/Enclave.spec.ts index c6a56ad4..d934737f 100644 --- a/packages/evm/test/encalve/Enclave.spec.ts +++ b/packages/evm/test/encalve/Enclave.spec.ts @@ -510,7 +510,7 @@ describe("Enclave", function () { it("emits InputPublished event"); }); - describe("publishComputationOutput()", function () { + describe("publishCiphertextOutput()", function () { it("reverts if E3 does not exist"); it("reverts if E3 has not been activated"); it("reverts if input deadline has not passed"); @@ -521,7 +521,7 @@ describe("Enclave", function () { it("emits CiphertextOutputPublished event"); }); - describe("publishExecutionOutput()", function () { + describe("publishPlaintextOutput()", function () { it("reverts if E3 does not exist"); it("reverts if E3 has not been activated"); it("reverts if ciphertextOutput has not been published"); From 71392635a19e7c329658a518e4171ec02b16a2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 12:12:00 +0200 Subject: [PATCH 33/62] Fix typo in folder name --- packages/evm/test/{encalve => enclave}/Enclave.fixture.ts | 0 packages/evm/test/{encalve => enclave}/Enclave.spec.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/evm/test/{encalve => enclave}/Enclave.fixture.ts (100%) rename packages/evm/test/{encalve => enclave}/Enclave.spec.ts (100%) diff --git a/packages/evm/test/encalve/Enclave.fixture.ts b/packages/evm/test/enclave/Enclave.fixture.ts similarity index 100% rename from packages/evm/test/encalve/Enclave.fixture.ts rename to packages/evm/test/enclave/Enclave.fixture.ts diff --git a/packages/evm/test/encalve/Enclave.spec.ts b/packages/evm/test/enclave/Enclave.spec.ts similarity index 100% rename from packages/evm/test/encalve/Enclave.spec.ts rename to packages/evm/test/enclave/Enclave.spec.ts From 6fc29b1d548eaf5d836614ffc96becc336f5f4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 12:40:38 +0200 Subject: [PATCH 34/62] Bump dependencies --- packages/evm/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/evm/package.json b/packages/evm/package.json index 416a24a8..a303f6d4 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -20,23 +20,23 @@ "@types/fs-extra": "^11.0.4", "@types/mocha": "^10.0.6", "@types/node": "^20.10.4", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@typescript-eslint/eslint-plugin": "^7.11.0", + "@typescript-eslint/parser": "^7.11.0", "chai": "^4.3.10", "cross-env": "^7.0.3", - "eslint": "^8.56.0", + "eslint": "^9.4.0", "eslint-config-prettier": "^9.1.0", "ethers": "^6.9.0", "fs-extra": "^11.2.0", "hardhat": "^2.19.2", "hardhat-deploy": "^0.12.1", - "hardhat-gas-reporter": "^1.0.9", + "hardhat-gas-reporter": "^2.2.0", "lodash": "^4.17.21", "mocha": "^10.2.0", "prettier": "^3.1.1", "prettier-plugin-solidity": "^1.2.0", "rimraf": "^5.0.5", - "solhint": "^4.0.0", + "solhint": "^5.0.1", "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.5", "ts-generator": "^0.1.1", From ebe490470aff690e1cf8edb331c56f6fd8930859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 12:40:51 +0200 Subject: [PATCH 35/62] Adjust prettier solidity version --- packages/evm/.prettierrc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/.prettierrc.yml b/packages/evm/.prettierrc.yml index 3b6e0857..99f4ab9a 100644 --- a/packages/evm/.prettierrc.yml +++ b/packages/evm/.prettierrc.yml @@ -11,7 +11,7 @@ trailingComma: "all" overrides: - files: "*.sol" options: - compiler: "0.8.17" + compiler: "0.8.26" parser: "solidity-parse" tabWidth: 4 - files: "*.ts" From 71a1824c70539fff75f8e80d134350dcdc533286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 13:10:38 +0200 Subject: [PATCH 36/62] Small gas optimization --- packages/evm/contracts/Enclave.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index cf4c1765..fadaecde 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -124,9 +124,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { executionModule: executionModule, inputValidator: inputValidator, outputVerifier: outputVerifier, - committeePublicKey: new bytes(0), - ciphertextOutput: new bytes(0), - plaintextOutput: new bytes(0) + committeePublicKey: hex"", + ciphertextOutput: hex"", + plaintextOutput: hex"" }); e3s[e3Id] = e3; From 860de67e30bf3121ea8680f50dcae7bbb242b0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 13:12:36 +0200 Subject: [PATCH 37/62] Remove unused variables --- packages/evm/test/enclave/Enclave.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/evm/test/enclave/Enclave.spec.ts b/packages/evm/test/enclave/Enclave.spec.ts index d934737f..c7451353 100644 --- a/packages/evm/test/enclave/Enclave.spec.ts +++ b/packages/evm/test/enclave/Enclave.spec.ts @@ -1,10 +1,7 @@ -import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; -import exp from "constants"; import { ethers } from "hardhat"; -import func from "../../deploy/deploy"; import { deployMockComputationModuleFixture } from "../mocks/MockComputationModule.fixture"; import { deployMockCypherNodeRegistryFixture } from "../mocks/MockCypherNodeRegistry.fixture"; import { deployMockExecutionModuleFixture } from "../mocks/MockExecutionModule.fixture"; From e1c3109e878f576761f3e669d6aa5172abf6bf5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:13:30 +0200 Subject: [PATCH 38/62] Include yarn.lock --- packages/evm/.gitignore | 3 +- packages/evm/yarn.lock | 4944 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 4945 insertions(+), 2 deletions(-) create mode 100644 packages/evm/yarn.lock diff --git a/packages/evm/.gitignore b/packages/evm/.gitignore index c3995b0d..ec7522bb 100644 --- a/packages/evm/.gitignore +++ b/packages/evm/.gitignore @@ -18,5 +18,4 @@ deployments .pnp.* coverage.json package-lock.json -pnpm-lock.yaml -yarn.lock +pnpm-lock.yaml \ No newline at end of file diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock new file mode 100644 index 00000000..f3c5f2a3 --- /dev/null +++ b/packages/evm/yarn.lock @@ -0,0 +1,4944 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" + integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== + dependencies: + "@babel/highlight" "^7.24.6" + picocolors "^1.0.0" + +"@babel/generator@7.17.7": + version "7.17.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad" + integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.23.0": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" + integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== + dependencies: + "@babel/types" "^7.24.6" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" + integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== + +"@babel/helper-function-name@^7.23.0": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" + integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== + dependencies: + "@babel/template" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" + integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" + integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== + dependencies: + "@babel/types" "^7.24.6" + +"@babel/helper-string-parser@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" + integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== + +"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" + integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== + +"@babel/highlight@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" + integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== + dependencies: + "@babel/helper-validator-identifier" "^7.24.6" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.20.5", "@babel/parser@^7.23.0", "@babel/parser@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" + integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== + +"@babel/template@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" + integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== + dependencies: + "@babel/code-frame" "^7.24.6" + "@babel/parser" "^7.24.6" + "@babel/types" "^7.24.6" + +"@babel/traverse@7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.17.0", "@babel/types@^7.23.0", "@babel/types@^7.24.6": + version "7.24.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" + integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== + dependencies: + "@babel/helper-string-parser" "^7.24.6" + "@babel/helper-validator-identifier" "^7.24.6" + to-fast-properties "^2.0.0" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/config-array@^0.15.1": + version "0.15.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.15.1.tgz#1fa78b422d98f4e7979f2211a1fde137e26c7d61" + integrity sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ== + dependencies: + "@eslint/object-schema" "^2.1.3" + debug "^4.3.1" + minimatch "^3.0.5" + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.4.0": + version "9.4.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.4.0.tgz#96a2edd37ec0551ce5f9540705be23951c008a0c" + integrity sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg== + +"@eslint/object-schema@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.3.tgz#e65ae80ee2927b4fd8c5c26b15ecacc2b2a6cc2a" + integrity sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw== + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + 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" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/units@5.7.0", "@ethersproject/units@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + 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" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + 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" + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" + integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@metamask/eth-sig-util@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + 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" + +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.3.0", "@noble/curves@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" + integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== + dependencies: + "@noble/hashes" "1.3.3" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.3.3", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + +"@noble/hashes@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nomicfoundation/edr-darwin-arm64@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.0.tgz#bbb43f0e01f40839b0bd38c2c443cb6910ae955f" + integrity sha512-7+rraFk9tCqvfemv9Ita5vTlSBAeO/S5aDKOgGRgYt0JEKZlrX161nDW6UfzMPxWl9GOLEDUzCEaYuNmXseUlg== + +"@nomicfoundation/edr-darwin-x64@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.0.tgz#b1ffcd9142418fd8498de34a7336b3f977907c86" + integrity sha512-+Hrc0mP9L6vhICJSfyGo/2taOToy1AIzVZawO3lU8Lf7oDQXfhQ4UkZnkWAs9SVu1eUwHUGGGE0qB8644piYgg== + +"@nomicfoundation/edr-linux-arm64-gnu@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.0.tgz#8173d16d4f6f2b3e82ba7096d2a1ea3619d8bfa7" + integrity sha512-4HUDMchNClQrVRfVTqBeSX92hM/3khCgpZkXP52qrnJPqgbdCxosOehlQYZ65wu0b/kaaZSyvACgvCLSQ5oSzQ== + +"@nomicfoundation/edr-linux-arm64-musl@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.0.tgz#b1ce293a7c3e0d9f70391e1aef1a82b83b997567" + integrity sha512-D4J935ZRL8xfnP3zIFlCI9jXInJ0loDUkCTLeCEbOf2uuDumWDghKNQlF1itUS+EHaR1pFVBbuwqq8hVK0dASg== + +"@nomicfoundation/edr-linux-x64-gnu@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.0.tgz#4c12c4e4bfd3d837f5663ad7cbf7cb6d5634ef83" + integrity sha512-6x7HPy+uN5Cb9N77e2XMmT6+QSJ+7mRbHnhkGJ8jm4cZvWuj2Io7npOaeHQ3YHK+TiQpTnlbkjoOIpEwpY3XZA== + +"@nomicfoundation/edr-linux-x64-musl@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.0.tgz#8842004aa1a47c504f10863687da28b65dca7baa" + integrity sha512-3HFIJSXgyubOiaN4MWGXx2xhTnhwlJk0PiSYNf9+L/fjBtcRkb2nM910ZJHTvqCb6OT98cUnaKuAYdXIW2amgw== + +"@nomicfoundation/edr-win32-x64-msvc@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.0.tgz#29d8bbb2edf9912a95f5453855cf17cdcb269957" + integrity sha512-CP4GsllEfXEz+lidcGYxKe5rDJ60TM5/blB5z/04ELVvw6/CK9eLcYeku7HV0jvV7VE6dADYKSdQyUkvd0El+A== + +"@nomicfoundation/edr@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.0.tgz#4895ecb6ef321136db837458949c37cce4a29459" + integrity sha512-T96DMSogO8TCdbKKctvxfsDljbhFOUKWc9fHJhSeUh71EEho2qR4951LKQF7t7UWEzguVYh/idQr5L/E3QeaMw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.4.0" + "@nomicfoundation/edr-darwin-x64" "0.4.0" + "@nomicfoundation/edr-linux-arm64-gnu" "0.4.0" + "@nomicfoundation/edr-linux-arm64-musl" "0.4.0" + "@nomicfoundation/edr-linux-x64-gnu" "0.4.0" + "@nomicfoundation/edr-linux-x64-musl" "0.4.0" + "@nomicfoundation/edr-win32-x64-msvc" "0.4.0" + +"@nomicfoundation/ethereumjs-common@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb" + integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.4" + +"@nomicfoundation/ethereumjs-rlp@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30" + integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw== + +"@nomicfoundation/ethereumjs-tx@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da" + integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38" + integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.4" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/hardhat-chai-matchers@^2.0.2": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.7.tgz#89d90b2d77a00f6fd8fe42eabe40a82b5e065075" + integrity sha512-RQfsiTwdf0SP+DtuNYvm4921X6VirCQq0Xyh+mnuGlTwEFSPZ/o27oQC+l+3Y/l48DDU7+ZcYBR+Fp+Rp94LfQ== + dependencies: + "@types/chai-as-promised" "^7.1.3" + chai-as-promised "^7.1.1" + deep-eql "^4.0.1" + ordinal "^1.0.3" + +"@nomicfoundation/hardhat-ethers@^3.0.5": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.6.tgz#e8ba7f9719de360c03501b85dae4999bb3a7e1c5" + integrity sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA== + dependencies: + debug "^4.1.1" + lodash.isequal "^4.5.0" + +"@nomicfoundation/hardhat-network-helpers@^1.0.10": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.11.tgz#64096829661b960b88679bd5c4fbcb50654672d1" + integrity sha512-uGPL7QSKvxrHRU69dx8jzoBvuztlLCtyFsbgfXIwIjnO3dqZRz2GNMHJoO3C3dIiUNM6jdNF4AUnoQKDscdYrA== + dependencies: + ethereumjs-util "^7.1.4" + +"@nomicfoundation/hardhat-toolbox@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-4.0.0.tgz#eb1f619218dd1414fa161dfec92d3e5e53a2f407" + integrity sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA== + +"@nomicfoundation/hardhat-verify@^2.0.2": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.8.tgz#6a77dc03de990a1a3aa8e6dc073c393263dbf258" + integrity sha512-x/OYya7A2Kcz+3W/J78dyDHxr0ezU23DKTrRKfy5wDPCnePqnr79vm8EXqX3gYps6IjPBYyGPZ9K6E5BnrWx5Q== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + lodash.clonedeep "^4.5.0" + semver "^6.3.0" + table "^6.8.0" + undici "^5.14.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" + integrity sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz#6e25ccdf6e2d22389c35553b64fe6f3fdaec432c" + integrity sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA== + +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz#0a224ea50317139caeebcdedd435c28a039d169c" + integrity sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz#dfa085d9ffab9efb2e7b383aed3f557f7687ac2b" + integrity sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz#c9e06b5d513dd3ab02a7ac069c160051675889a4" + integrity sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz#8d328d16839e52571f72f2998c81e46bf320f893" + integrity sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz#9b49d0634b5976bb5ed1604a1e1b736f390959bb" + integrity sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz#e2867af7264ebbcc3131ef837878955dd6a3676f" + integrity sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz#0685f78608dd516c8cdfb4896ed451317e559585" + integrity sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz#c9a44f7108646f083b82e851486e0f6aeb785836" + integrity sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz#f5f4d36d3f66752f59a57e7208cd856f3ddf6f2d" + integrity sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.1" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.1" + "@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" + +"@openzeppelin/contracts-upgradeable@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105" + integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pnpm/config.env-replace@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" + integrity sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w== + +"@pnpm/network.ca-file@^1.0.1": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz#2ab05e09c1af0cdf2fcf5035bea1484e222f7983" + integrity sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA== + dependencies: + graceful-fs "4.2.10" + +"@pnpm/npm-conf@^2.1.0": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz#0058baf1c26cbb63a828f0193795401684ac86f0" + integrity sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA== + dependencies: + "@pnpm/config.env-replace" "^1.1.0" + "@pnpm/network.ca-file" "^1.0.1" + config-chain "^1.1.11" + +"@prettier/sync@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@prettier/sync/-/sync-0.3.0.tgz#91f2cfc23490a21586d1cf89c6f72157c000ca1e" + integrity sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw== + +"@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.4": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d" + integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g== + +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + +"@scure/bip32@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== + dependencies: + "@noble/curves" "~1.2.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.2" + +"@scure/bip32@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" + integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== + dependencies: + "@noble/curves" "~1.3.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" + +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" + integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== + dependencies: + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^5.2.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.6.0.tgz#41dd6093d34652cddb5d5bdeee04eafc33826668" + integrity sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g== + +"@solidity-parser/parser@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.17.0.tgz#52a2fcc97ff609f72011014e4c5b485ec52243ef" + integrity sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw== + +"@solidity-parser/parser@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" + integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== + +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + +"@trivago/prettier-plugin-sort-imports@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz#725f411646b3942193a37041c84e0b2116339789" + integrity sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ== + dependencies: + "@babel/generator" "7.17.7" + "@babel/parser" "^7.20.5" + "@babel/traverse" "7.23.2" + "@babel/types" "7.17.0" + javascript-natural-sort "0.7.1" + lodash "^4.17.21" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@typechain/ethers-v6@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz#42fe214a19a8b687086c93189b301e2b878797ea" + integrity sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/hardhat@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-9.1.0.tgz#6985015f01dfb37ef2ca8a29c742d05890351ddc" + integrity sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA== + dependencies: + fs-extra "^9.1.0" + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + +"@types/chai-as-promised@^7.1.3": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.3.11": + version "4.3.16" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" + integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== + +"@types/fs-extra@^11.0.4": + version "11.0.4" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.4.tgz#e16a863bb8843fba8c5004362b5a73e17becca45" + integrity sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ== + dependencies: + "@types/jsonfile" "*" + "@types/node" "*" + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/http-cache-semantics@^4.0.2": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" + integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== + +"@types/jsonfile@*": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.4.tgz#614afec1a1164e7d670b4a7ad64df3e7beb7b702" + integrity sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ== + dependencies: + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/minimatch@*": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^10.0.6": + version "10.0.6" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.6.tgz#818551d39113081048bdddbef96701b4e8bb9d1b" + integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== + +"@types/node@*", "@types/node@^20.10.4": + version "20.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.0.tgz#49ceec7b34f8621470cff44677fa9d461a477f17" + integrity sha512-5cHBxFGJx6L4s56Bubp4fglrEpmyJypsqI6RgzMfBHWUJQGWAAi8cWcgetEbZXHYXo9C2Fa4EEds/uSyS4cxmA== + dependencies: + undici-types "~5.26.4" + +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + +"@types/pbkdf2@^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" + integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + +"@types/qs@^6.9.7": + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" + integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz#f90f0914657ead08e1c75f66939c926edeab42dd" + integrity sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.11.0" + "@typescript-eslint/type-utils" "7.11.0" + "@typescript-eslint/utils" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/parser@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.11.0.tgz#525ad8bee54a8f015f134edd241d91b84ab64839" + integrity sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg== + dependencies: + "@typescript-eslint/scope-manager" "7.11.0" + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/typescript-estree" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz#cf5619b01de62a226a59add15a02bde457335d1d" + integrity sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw== + dependencies: + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + +"@typescript-eslint/type-utils@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz#ac216697d649084fedf4a910347b9642bd0ff099" + integrity sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg== + dependencies: + "@typescript-eslint/typescript-estree" "7.11.0" + "@typescript-eslint/utils" "7.11.0" + debug "^4.3.4" + ts-api-utils "^1.3.0" + +"@typescript-eslint/types@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.11.0.tgz#5e9702a5e8b424b7fc690e338d359939257d6722" + integrity sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w== + +"@typescript-eslint/typescript-estree@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz#7cbc569bc7336c3a494ceaf8204fdee5d5dbb7fa" + integrity sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ== + dependencies: + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/visitor-keys" "7.11.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.11.0.tgz#524f047f2209959424c3ef689b0d83b3bc09919c" + integrity sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "7.11.0" + "@typescript-eslint/types" "7.11.0" + "@typescript-eslint/typescript-estree" "7.11.0" + +"@typescript-eslint/visitor-keys@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz#2c50cd292e67645eec05ac0830757071b4a4d597" + integrity sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ== + dependencies: + "@typescript-eslint/types" "7.11.0" + eslint-visitor-keys "^3.4.3" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== + +abitype@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" + integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.11.3, acorn@^8.4.1: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4, ajv@^6.12.6: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.14.0.tgz#f514ddfd4756abb200e1704414963620a625ebbb" + integrity sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +antlr4@^4.13.1-patch-1: + version "4.13.1-patch-1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1-patch-1.tgz#946176f863f890964a050c4f18c47fd6f7e57602" + integrity sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +ast-parents@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" + integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async@1.x: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.6.7: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== + +bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +brotli-wasm@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brotli-wasm/-/brotli-wasm-2.0.1.tgz#2b3f4dc3db0c3e60d2635c055e6bac4ddf4bd3f5" + integrity sha512-+3USgYsC7bzb5yU0/p2HnnynZl0ak0E6uoIm4UW4Aby/8s8HFCq6NCfrrf1E9c3O8OCSzq3oYO1tUVqIi61Nww== + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.8: + version "10.2.14" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.14.tgz#eb915b665fda41b79652782df3f553449c406b9d" + integrity sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ== + dependencies: + "@types/http-cache-semantics" "^4.0.2" + get-stream "^6.0.1" + http-cache-semantics "^4.1.1" + keyv "^4.5.3" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + 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.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + +chai-as-promised@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" + integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== + dependencies: + check-error "^1.0.2" + +chai@^4.3.10: + version "4.4.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" + +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +"charenc@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + +check-error@^1.0.2, check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^3.4.0, chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cli-table3@^0.6.3: + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +config-chain@^1.1.11: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cosmiconfig@^8.0.0: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +"crypt@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +death@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-eql@^4.0.1, deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-extend@^0.6.0, deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +difflib@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e" + integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w== + dependencies: + heap ">= 0.2.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +elliptic@^6.5.2, elliptic@^6.5.4: + version "6.5.5" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +enquirer@^2.3.0, enquirer@^2.3.6: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A== + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + +eslint-scope@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" + integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + +eslint@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.4.0.tgz#79150c3610ae606eb131f1d648d5f43b3d45f3cd" + integrity sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/config-array" "^0.15.1" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.4.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.3.0" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.0.1" + eslint-visitor-keys "^4.0.0" + espree "^10.0.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" + integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== + dependencies: + acorn "^8.11.3" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.0.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +ethereum-bloom-filters@^1.0.6: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz#b3fc1eb789509ee30db0bf99a2988ccacb8d0397" + integrity sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw== + dependencies: + "@noble/hashes" "^1.4.0" + +ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2, ethereum-cryptography@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" + integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== + dependencies: + "@noble/curves" "1.3.0" + "@noble/hashes" "1.3.3" + "@scure/bip32" "1.3.3" + "@scure/bip39" "1.2.2" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^7.1.4: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethers@^5.7.0, ethers@~5.7.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^6.9.0: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.12.2.tgz#f2724ec33bcf802b6786579e943b6e38a2ba3612" + integrity sha512-MNfR2kzZyNF8bRNDSmjM+rT1+yqCgYNqfrXyNnpiNId2MQPiAOOr/7lrgdrdwoBxzKPSnSYZaGb5lcNyvzhuvA== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2, fast-diff@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.0.3, fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +ghost-testrpc@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz#c4de9557b1d1ae7b2d20bbe474a91378ca90ce92" + integrity sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ== + dependencies: + chalk "^2.4.2" + node-emoji "^1.10.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@8.1.0, glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +glob@^10.3.10, glob@^10.3.7: + version "10.4.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" + integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + path-scurry "^1.11.1" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA== + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.2, glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@^12.1.0: + version "12.6.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" + integrity sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.8" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +handlebars@^4.0.1: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +hardhat-deploy@^0.12.1: + version "0.12.4" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.12.4.tgz#5ebef37f1004f52a74987213b0465ad7c9433fb2" + integrity sha512-bYO8DIyeGxZWlhnMoCBon9HNZb6ji0jQn7ngP1t5UmGhC8rQYhji7B73qETMOFhzt5ECZPr+U52duj3nubsqdQ== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + "@ethersproject/solidity" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wallet" "^5.7.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.7.0" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-ethers "^5.0.0" + +hardhat-gas-reporter@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.0.tgz#be50f5bc173e5dbb1dbfdfa557e192f34b3728c5" + integrity sha512-eAlLWnyDpQ+wJXgSCZsM0yt+rQm3ryJia1I1Hoi94LzlIfuSPcsMQM12VO6UHmAFLvXvoKxXPJ3ZYk0Kz+7CDQ== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/units" "^5.7.0" + "@solidity-parser/parser" "^0.18.0" + axios "^1.6.7" + brotli-wasm "^2.0.1" + chalk "4.1.2" + cli-table3 "^0.6.3" + ethereum-cryptography "^2.1.3" + glob "^10.3.10" + jsonschema "^1.4.1" + lodash "^4.17.21" + markdown-table "2.0.0" + sha1 "^1.1.1" + viem "2.7.14" + +hardhat@^2.19.2: + version "2.22.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.5.tgz#7e1a4311fa9e34a1cfe337784eae06706f6469a5" + integrity sha512-9Zq+HonbXCSy6/a13GY1cgHglQRfh4qkzmj1tpPlhxJDwNVnhxlReV6K7hCWFKlOrV13EQwsdcD0rjcaQKWRZw== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/edr" "^0.4.0" + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-tx" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +"heap@>= 0.2.0": + version "0.2.7" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" + integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +http-cache-semantics@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http2-wrapper@^2.1.10: + version "2.2.1" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.1.tgz#310968153dcdedb160d8b72114363ef5fce1f64a" + integrity sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + +immutable@^4.0.0-rc.12: + version "4.3.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" + integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ== + +import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + +jackspeak@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.1.2.tgz#eada67ea949c6b71de50f1b09c92a961897b90ab" + integrity sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +javascript-natural-sort@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.x: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonschema@^1.2.4, jsonschema@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" + integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== + +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^4.5.3, keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" + +latest-version@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" + integrity sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg== + dependencies: + package-json "^8.1.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + +lru-cache@^10.2.0: + version "10.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +markdown-table@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" + integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== + dependencies: + repeat-string "^1.0.0" + +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== + +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + +micromatch@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mkdirp@0.5.x, mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0, mocha@^10.2.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" + integrity sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "8.1.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-emoji@^1.10.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" + integrity sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A== + dependencies: + lodash "^4.17.21" + +node-gyp-build@^4.2.0: + version "4.8.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5" + integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== + +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg== + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.1.tgz#9b7d96af9836577c58f5883e939365fa15623a4a" + integrity sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w== + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== + +once@1.x, once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +ordinal@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" + integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +package-json@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-8.1.1.tgz#3e9948e43df40d1e8e78a85485f1070bf8f03dc8" + integrity sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA== + dependencies: + got "^12.1.0" + registry-auth-token "^5.0.1" + registry-url "^6.0.0" + semver "^7.3.7" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +picocolors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier-plugin-solidity@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.3.1.tgz#59944d3155b249f7f234dee29f433524b9a4abcf" + integrity sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA== + dependencies: + "@solidity-parser/parser" "^0.17.0" + semver "^7.5.4" + solidity-comments-extractor "^0.0.8" + +prettier@^2.1.2, prettier@^2.3.1, prettier@^2.8.3: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +prettier@^3.1.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.0.tgz#d173ea0524a691d4c0b1181752f2b46724328cdf" + integrity sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g== + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@^6.9.4: + version "6.12.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" + integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== + dependencies: + side-channel "^1.0.6" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== + dependencies: + resolve "^1.1.6" + +recursive-readdir@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== + dependencies: + minimatch "^3.0.5" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +registry-auth-token@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" + integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== + dependencies: + "@pnpm/npm-conf" "^2.1.0" + +registry-url@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-6.0.1.tgz#056d9343680f2f64400032b1e199faa692286c58" + integrity sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q== + dependencies: + rc "1.2.8" + +repeat-string@^1.0.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.1.6, resolve@^1.8.1: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== + dependencies: + lowercase-keys "^3.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.2.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^5.0.5: + version "5.0.7" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" + integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== + dependencies: + glob "^10.3.7" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sc-istanbul@^0.4.5: + version "0.4.6" + resolved "https://registry.yarnpkg.com/sc-istanbul/-/sc-istanbul-0.4.6.tgz#cf6784355ff2076f92d70d59047d71c13703e839" + integrity sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g== + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +scrypt-js@3.0.1, scrypt-js@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.4, semver@^7.3.7, semver@^7.5.2, semver@^7.5.4, semver@^7.6.0: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA== + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shelljs@^0.8.3: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solhint-plugin-prettier@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.1.0.tgz#2f46999e26d6c6bc80281c22a7a21e381175bef7" + integrity sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw== + dependencies: + "@prettier/sync" "^0.3.0" + prettier-linter-helpers "^1.0.0" + +solhint@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-5.0.1.tgz#f0f783bd9d945e5a27b102295a3f28edba241d6c" + integrity sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg== + dependencies: + "@solidity-parser/parser" "^0.18.0" + ajv "^6.12.6" + antlr4 "^4.13.1-patch-1" + ast-parents "^0.0.1" + chalk "^4.1.2" + commander "^10.0.0" + cosmiconfig "^8.0.0" + fast-diff "^1.2.0" + glob "^8.0.3" + ignore "^5.2.4" + js-yaml "^4.1.0" + latest-version "^7.0.0" + lodash "^4.17.21" + pluralize "^8.0.0" + semver "^7.5.2" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" + optionalDependencies: + prettier "^2.8.3" + +solidity-comments-extractor@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.8.tgz#f6e148ab0c49f30c1abcbecb8b8df01ed8e879f8" + integrity sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g== + +solidity-coverage@^0.8.5: + version "0.8.12" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.12.tgz#c4fa2f64eff8ada7a1387b235d6b5b0e6c6985ed" + integrity sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw== + dependencies: + "@ethersproject/abi" "^5.0.9" + "@solidity-parser/parser" "^0.18.0" + chalk "^2.4.2" + death "^1.1.0" + difflib "^0.2.4" + fs-extra "^8.1.0" + ghost-testrpc "^0.0.2" + global-modules "^2.0.0" + globby "^10.0.1" + jsonschema "^1.2.4" + lodash "^4.17.21" + mocha "^10.2.0" + node-emoji "^1.10.0" + pify "^4.0.1" + recursive-readdir "^2.2.2" + sc-istanbul "^0.4.5" + semver "^7.3.4" + shelljs "^0.8.3" + web3-utils "^1.3.6" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA== + dependencies: + amdefine ">=0.0.4" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^6.8.0, table@^6.8.1: + version "6.8.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +ts-api-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-command-line-args@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +typechain@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.2.tgz#1090dd8d9c57b6ef2aed3640a516bdbf01b00d73" + integrity sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typescript@^5.3.3: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +uglify-js@^3.1.4: + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +undici@^5.14.0: + version "5.28.4" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== + dependencies: + "@fastify/busboy" "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +uri-js@^4.2.2, uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +viem@2.7.14: + version "2.7.14" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.7.14.tgz#347d316cb5400f0b896b2205b1bc8073aa5e27e0" + integrity sha512-5b1KB1gXli02GOQHZIUsRluNUwssl2t4hqdFAzyWPwJ744N83jAOBOjOkrGz7K3qMIv9b0GQt3DoZIErSQTPkQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "1.0.0" + isows "1.0.3" + ws "8.13.0" + +web3-utils@^1.3.6: + version "1.10.4" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.4.tgz#0daee7d6841641655d8b3726baf33b08eda1cbec" + integrity sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +which@^1.1.1, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +word-wrap@^1.2.5, word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-ethers@^5.0.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-5.7.2.tgz#e965a9926e6f8168963ab565dd6ad0d38c4f7f18" + integrity sha512-D+wn4nkGixUOek9ZsVvIZ/MHponQ5xvw74FSbDJDv6SLCI4LZALOAc8lF3b1ml8nOkpeE2pGV0VKmHTSquRNJg== + dependencies: + ethers "~5.7.0" From bb628ea968c4849dda6003680c4cad134738ad7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:14:29 +0200 Subject: [PATCH 39/62] Simplify Enclave.fixture setup --- packages/evm/test/enclave/Enclave.fixture.ts | 27 +++-- packages/evm/test/enclave/Enclave.spec.ts | 107 +++++++++---------- 2 files changed, 70 insertions(+), 64 deletions(-) diff --git a/packages/evm/test/enclave/Enclave.fixture.ts b/packages/evm/test/enclave/Enclave.fixture.ts index 3c259eda..b2815e0a 100644 --- a/packages/evm/test/enclave/Enclave.fixture.ts +++ b/packages/evm/test/enclave/Enclave.fixture.ts @@ -1,16 +1,25 @@ +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ethers } from "hardhat"; -import type { Enclave } from "../../types/contracts/Enclave"; -import type { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; +import { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; -export async function deployEnclaveFixture() { +export async function deployEnclaveFixture({ + owner, + registry, + maxDuration, +}: { + owner?: SignerWithAddress; + registry?: SignerWithAddress; + maxDuration?: number; +} = {}) { // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await ethers.getSigners(); - const maxDuration = 60 * 60 * 24 * 30; + const [account1, account2] = await ethers.getSigners(); - const Enclave = (await ethers.getContractFactory("Enclave")) as Enclave__factory; - const enclave = (await Enclave.deploy(owner.address, otherAccount.address, maxDuration)) as Enclave; - const enclave_address = await enclave.getAddress(); + owner = owner || account1; + registry = registry || account2; + maxDuration = maxDuration || 60 * 60 * 24 * 30; - return { Enclave, enclave, enclave_address, maxDuration, owner, otherAccount }; + const deployment = await (await ethers.getContractFactory("Enclave")).deploy(owner, registry, maxDuration); + + return Enclave__factory.connect(await deployment.getAddress(), owner); } diff --git a/packages/evm/test/enclave/Enclave.spec.ts b/packages/evm/test/enclave/Enclave.spec.ts index c7451353..9bc58e74 100644 --- a/packages/evm/test/enclave/Enclave.spec.ts +++ b/packages/evm/test/enclave/Enclave.spec.ts @@ -11,6 +11,7 @@ import type { Signers } from "../types"; import { deployEnclaveFixture } from "./Enclave.fixture"; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); +const AddressTwo = "0x0000000000000000000000000000000000000002"; describe("Enclave", function () { before(async function () { @@ -18,43 +19,33 @@ describe("Enclave", function () { const signers = await ethers.getSigners(); this.signers.admin = signers[0]; - - this.loadFixture = loadFixture; }); beforeEach(async function () { - const { Enclave, enclave, enclave_address, maxDuration, owner, otherAccount } = - await this.loadFixture(deployEnclaveFixture); - this.Enclave = Enclave; + const enclave = await loadFixture(deployEnclaveFixture); this.enclave = enclave; - this.enclave_address = enclave_address; - this.maxDuration = maxDuration; - this.owner = owner; - this.otherAccount = otherAccount; - const { mockComputationModule, mockComputationModule_address } = await this.loadFixture( + const { mockComputationModule, mockComputationModule_address } = await loadFixture( deployMockComputationModuleFixture, ); this.mockComputationModule = mockComputationModule; this.mockComputationModule_address = mockComputationModule_address; - const { mockOutputVerifier, mockOutputVerifier_address } = await this.loadFixture(deployMockOutputVerifierFixture); + const { mockOutputVerifier, mockOutputVerifier_address } = await loadFixture(deployMockOutputVerifierFixture); this.mockOutputVerifier = mockOutputVerifier; this.mockOutputVerifier_address = mockOutputVerifier_address; - const { mockCypherNodeRegistry, mockCypherNodeRegistry_address } = await this.loadFixture( + const { mockCypherNodeRegistry, mockCypherNodeRegistry_address } = await loadFixture( deployMockCypherNodeRegistryFixture, ); this.mockCypherNodeRegistry = mockCypherNodeRegistry; this.mockCypherNodeRegistry_address = mockCypherNodeRegistry_address; - const { mockExecutionModule, mockExecutionModule_address } = await this.loadFixture( - deployMockExecutionModuleFixture, - ); + const { mockExecutionModule, mockExecutionModule_address } = await loadFixture(deployMockExecutionModuleFixture); this.mockExecutionModule = mockExecutionModule; this.mockExecutionModule_address = mockExecutionModule_address; - const { mockInputValidator, mockInputValidator_address } = await this.loadFixture(deployMockInputValidatorFixture); + const { mockInputValidator, mockInputValidator_address } = await loadFixture(deployMockInputValidatorFixture); this.mockInputValidator = mockInputValidator; this.mockInputValidator_address = mockInputValidator_address; @@ -75,17 +66,16 @@ describe("Enclave", function () { describe("constructor / initialize()", function () { it("correctly sets owner", async function () { - // uses the fixture deployment with this.owner set as the owner const owner1 = await this.enclave.owner(); - // create a new deployment with this.otherAccount as the owner - // note that this.owner is msg.sender in both cases - const enclave = await this.Enclave.deploy(this.otherAccount.address, this.otherAccount.address, this.maxDuration); - const owner2 = await enclave.owner(); + const [, , , otherOwner, otherRegistry] = await ethers.getSigners(); + + const enclave = await deployEnclaveFixture({ owner: otherOwner, registry: otherRegistry }); // expect the owner to be the same as the one set in the fixture - expect(owner1).to.equal(this.owner); + expect(owner1).to.not.equal(otherOwner); // expect the owner to be the same as the one set in the new deployment - expect(owner2).to.equal(this.otherAccount); + expect(await enclave.owner()).to.equal(otherOwner); + expect(await enclave.cypherNodeRegistry()).to.equal(otherRegistry); }); it("correctly sets cypherNodeRegistry address", async function () { @@ -95,17 +85,17 @@ describe("Enclave", function () { }); it("correctly sets max duration", async function () { - const maxDuration = await this.enclave.maxDuration(); - - expect(maxDuration).to.equal(this.maxDuration); + const enclave = await deployEnclaveFixture({ maxDuration: 9876 }); + expect(await enclave.maxDuration()).to.equal(9876); }); }); describe("setMaxDuration()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).setMaxDuration(1)) + const [, , , notTheOwner] = await ethers.getSigners(); + await expect(this.enclave.connect(notTheOwner).setMaxDuration(1)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount.address); + .withArgs(notTheOwner); }); it("set max duration correctly", async function () { await this.enclave.setMaxDuration(1); @@ -125,9 +115,11 @@ describe("Enclave", function () { describe("setCypherNodeRegistry()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).setCypherNodeRegistry(this.otherAccount.address)) + const [, , , notTheOwner] = await ethers.getSigners(); + + await expect(this.enclave.connect(notTheOwner).setCypherNodeRegistry(AddressTwo)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount.address); + .withArgs(notTheOwner); }); it("reverts if given address(0)", async function () { await expect(this.enclave.setCypherNodeRegistry(ethers.ZeroAddress)) @@ -140,20 +132,21 @@ describe("Enclave", function () { .withArgs(this.mockCypherNodeRegistry_address); }); it("sets cypherNodeRegistry correctly", async function () { - await this.enclave.setCypherNodeRegistry(this.owner.address); + expect(await this.enclave.cypherNodeRegistry()).to.not.equal(AddressTwo); - const cypherNodeRegistry = await this.enclave.cypherNodeRegistry(); - expect(cypherNodeRegistry).to.equal(this.owner.address); + await this.enclave.setCypherNodeRegistry(AddressTwo); + + expect(await this.enclave.cypherNodeRegistry()).to.equal(AddressTwo); }); it("returns true if cypherNodeRegistry is set successfully", async function () { - const result = await this.enclave.setCypherNodeRegistry.staticCall(this.owner.address); + const result = await this.enclave.setCypherNodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits CypherNodeRegistrySet event", async function () { - await expect(this.enclave.setCypherNodeRegistry(this.owner.address)) + await expect(this.enclave.setCypherNodeRegistry(AddressTwo)) .to.emit(this.enclave, "CypherNodeRegistrySet") - .withArgs(this.owner.address); + .withArgs(AddressTwo); }); }); @@ -188,9 +181,10 @@ describe("Enclave", function () { describe("enableComputationModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).enableComputationModule(this.mockComputationModule_address)) + const [, , , notTheOwner] = await ethers.getSigners(); + await expect(this.enclave.connect(notTheOwner).enableComputationModule(this.mockComputationModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount); + .withArgs(notTheOwner); }); it("reverts if computation module is already enabled", async function () { await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) @@ -202,27 +196,27 @@ describe("Enclave", function () { expect(enabled).to.be.true; }); it("returns true if computation module is enabled successfully", async function () { - const result = await this.enclave.enableComputationModule.staticCall(this.otherAccount.address); - + const result = await this.enclave.enableComputationModule.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits ComputationModuleEnabled event", async function () { - await expect(this.enclave.enableComputationModule(this.otherAccount.address)) + await expect(this.enclave.enableComputationModule(AddressTwo)) .to.emit(this.enclave, "ComputationModuleEnabled") - .withArgs(this.otherAccount.address); + .withArgs(AddressTwo); }); }); describe("disableComputationModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).disableComputationModule(this.mockComputationModule_address)) + const [, , , notTheOwner] = await ethers.getSigners(); + await expect(this.enclave.connect(notTheOwner).disableComputationModule(this.mockComputationModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount.address); + .withArgs(notTheOwner); }); it("reverts if computation module is not enabled", async function () { - await expect(this.enclave.disableComputationModule(this.otherAccount.address)) + await expect(this.enclave.disableComputationModule(AddressTwo)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.otherAccount.address); + .withArgs(AddressTwo); }); it("disables computation module correctly", async function () { await this.enclave.disableComputationModule(this.mockComputationModule_address); @@ -244,9 +238,10 @@ describe("Enclave", function () { describe("enableExecutionModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).enableExecutionModule(this.mockExecutionModule_address)) + const [, , , notTheOwner] = await ethers.getSigners(); + await expect(this.enclave.connect(notTheOwner).enableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount.address); + .withArgs(notTheOwner.address); }); it("reverts if execution module is already enabled", async function () { await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) @@ -258,27 +253,29 @@ describe("Enclave", function () { expect(enabled).to.be.true; }); it("returns true if execution module is enabled successfully", async function () { - const result = await this.enclave.enableExecutionModule.staticCall(this.otherAccount.address); + const result = await this.enclave.enableExecutionModule.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits ExecutionModuleEnabled event", async function () { - await expect(this.enclave.enableExecutionModule(this.otherAccount)) + await expect(this.enclave.enableExecutionModule(AddressTwo)) .to.emit(this.enclave, "ExecutionModuleEnabled") - .withArgs(this.otherAccount); + .withArgs(AddressTwo); }); }); describe("disableExecutionModule()", function () { it("reverts if not called by owner", async function () { - await expect(this.enclave.connect(this.otherAccount).disableExecutionModule(this.mockExecutionModule_address)) + const [, , , notTheOwner] = await ethers.getSigners(); + + await expect(this.enclave.connect(notTheOwner).disableExecutionModule(this.mockExecutionModule_address)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") - .withArgs(this.otherAccount.address); + .withArgs(notTheOwner); }); it("reverts if execution module is not enabled", async function () { - await expect(this.enclave.disableExecutionModule(this.otherAccount.address)) + await expect(this.enclave.disableExecutionModule(AddressTwo)) .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") - .withArgs(this.otherAccount.address); + .withArgs(AddressTwo); }); it("disables execution module correctly", async function () { await this.enclave.disableExecutionModule(this.mockExecutionModule_address); From be79dcee5eefe1d70c0e20f2bb2f8aebd622c1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:23:34 +0200 Subject: [PATCH 40/62] Reorganize test folder structure --- packages/evm/test/{enclave => }/Enclave.spec.ts | 14 +++++++------- .../test/{enclave => fixtures}/Enclave.fixture.ts | 0 .../MockComputationModule.fixture.ts | 0 .../MockCypherNodeRegistry.fixture.ts | 0 .../MockExecutionModule.fixture.ts | 0 .../MockInputValidator.fixture.ts | 0 .../MockOutputVerifier.fixture.ts | 0 7 files changed, 7 insertions(+), 7 deletions(-) rename packages/evm/test/{enclave => }/Enclave.spec.ts (97%) rename packages/evm/test/{enclave => fixtures}/Enclave.fixture.ts (100%) rename packages/evm/test/{mocks => fixtures}/MockComputationModule.fixture.ts (100%) rename packages/evm/test/{mocks => fixtures}/MockCypherNodeRegistry.fixture.ts (100%) rename packages/evm/test/{mocks => fixtures}/MockExecutionModule.fixture.ts (100%) rename packages/evm/test/{mocks => fixtures}/MockInputValidator.fixture.ts (100%) rename packages/evm/test/{mocks => fixtures}/MockOutputVerifier.fixture.ts (100%) diff --git a/packages/evm/test/enclave/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts similarity index 97% rename from packages/evm/test/enclave/Enclave.spec.ts rename to packages/evm/test/Enclave.spec.ts index 9bc58e74..dfb006ae 100644 --- a/packages/evm/test/enclave/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -2,13 +2,13 @@ import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; -import { deployMockComputationModuleFixture } from "../mocks/MockComputationModule.fixture"; -import { deployMockCypherNodeRegistryFixture } from "../mocks/MockCypherNodeRegistry.fixture"; -import { deployMockExecutionModuleFixture } from "../mocks/MockExecutionModule.fixture"; -import { deployMockInputValidatorFixture } from "../mocks/MockInputValidator.fixture"; -import { deployMockOutputVerifierFixture } from "../mocks/MockOutputVerifier.fixture"; -import type { Signers } from "../types"; -import { deployEnclaveFixture } from "./Enclave.fixture"; +import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; +import { deployMockComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; +import { deployMockCypherNodeRegistryFixture } from "./fixtures/MockCypherNodeRegistry.fixture"; +import { deployMockExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; +import { deployMockInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; +import { deployMockOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; +import { Signers } from "./types"; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const AddressTwo = "0x0000000000000000000000000000000000000002"; diff --git a/packages/evm/test/enclave/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts similarity index 100% rename from packages/evm/test/enclave/Enclave.fixture.ts rename to packages/evm/test/fixtures/Enclave.fixture.ts diff --git a/packages/evm/test/mocks/MockComputationModule.fixture.ts b/packages/evm/test/fixtures/MockComputationModule.fixture.ts similarity index 100% rename from packages/evm/test/mocks/MockComputationModule.fixture.ts rename to packages/evm/test/fixtures/MockComputationModule.fixture.ts diff --git a/packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts similarity index 100% rename from packages/evm/test/mocks/MockCypherNodeRegistry.fixture.ts rename to packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts diff --git a/packages/evm/test/mocks/MockExecutionModule.fixture.ts b/packages/evm/test/fixtures/MockExecutionModule.fixture.ts similarity index 100% rename from packages/evm/test/mocks/MockExecutionModule.fixture.ts rename to packages/evm/test/fixtures/MockExecutionModule.fixture.ts diff --git a/packages/evm/test/mocks/MockInputValidator.fixture.ts b/packages/evm/test/fixtures/MockInputValidator.fixture.ts similarity index 100% rename from packages/evm/test/mocks/MockInputValidator.fixture.ts rename to packages/evm/test/fixtures/MockInputValidator.fixture.ts diff --git a/packages/evm/test/mocks/MockOutputVerifier.fixture.ts b/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts similarity index 100% rename from packages/evm/test/mocks/MockOutputVerifier.fixture.ts rename to packages/evm/test/fixtures/MockOutputVerifier.fixture.ts From 50e9c2e06a9f349daa2851123053216f153f608a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:23:50 +0200 Subject: [PATCH 41/62] Remove unnecessary test hook --- packages/evm/test/Enclave.spec.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index dfb006ae..9b34b037 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -14,13 +14,6 @@ const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const AddressTwo = "0x0000000000000000000000000000000000000002"; describe("Enclave", function () { - before(async function () { - this.signers = {} as Signers; - - const signers = await ethers.getSigners(); - this.signers.admin = signers[0]; - }); - beforeEach(async function () { const enclave = await loadFixture(deployEnclaveFixture); this.enclave = enclave; From c4de25ac66433d301b02b0c67cfcc3fbb753ddfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:24:30 +0200 Subject: [PATCH 42/62] Delete unused file --- packages/evm/test/types.ts | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 packages/evm/test/types.ts diff --git a/packages/evm/test/types.ts b/packages/evm/test/types.ts deleted file mode 100644 index 37487397..00000000 --- a/packages/evm/test/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/dist/src/signer-with-address"; - -import type { Enclave } from "../types/Enclave"; - -type Fixture = () => Promise; - -declare module "mocha" { - export interface Context { - enclave: Enclave; - loadFixture: (fixture: Fixture) => Promise; - signers: Signers; - } -} - -export interface Signers { - admin: SignerWithAddress; -} From 8e16a390461bf82adf7d989b7083ec36788a61d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:34:47 +0200 Subject: [PATCH 43/62] Simplify computationModuleFixture --- packages/evm/test/Enclave.spec.ts | 40 ++++++++++--------- .../fixtures/MockComputationModule.fixture.ts | 13 ++---- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 9b34b037..4380a0ee 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -3,12 +3,11 @@ import { expect } from "chai"; import { ethers } from "hardhat"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; -import { deployMockComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; +import { deployComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; import { deployMockCypherNodeRegistryFixture } from "./fixtures/MockCypherNodeRegistry.fixture"; import { deployMockExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; import { deployMockInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; import { deployMockOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; -import { Signers } from "./types"; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const AddressTwo = "0x0000000000000000000000000000000000000002"; @@ -18,11 +17,7 @@ describe("Enclave", function () { const enclave = await loadFixture(deployEnclaveFixture); this.enclave = enclave; - const { mockComputationModule, mockComputationModule_address } = await loadFixture( - deployMockComputationModuleFixture, - ); - this.mockComputationModule = mockComputationModule; - this.mockComputationModule_address = mockComputationModule_address; + const computationModule = await loadFixture(deployComputationModuleFixture); const { mockOutputVerifier, mockOutputVerifier_address } = await loadFixture(deployMockOutputVerifierFixture); this.mockOutputVerifier = mockOutputVerifier; @@ -43,14 +38,14 @@ describe("Enclave", function () { this.mockInputValidator_address = mockInputValidator_address; await this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address); - await this.enclave.enableComputationModule(this.mockComputationModule_address); + await this.enclave.enableComputationModule(await computationModule.getAddress()); await this.enclave.enableExecutionModule(this.mockExecutionModule_address); this.requestParams = { poolId: 1n, threshold: [2n, 2n], duration: time.duration.days(30), - computationModule: this.mockComputationModule_address, + computationModule: await computationModule.getAddress(), cMParams: abiCoder.encode(["address"], [this.mockInputValidator_address]), executionModule: this.mockExecutionModule_address, eMParams: abiCoder.encode(["address"], [this.mockOutputVerifier_address]), @@ -175,17 +170,20 @@ describe("Enclave", function () { describe("enableComputationModule()", function () { it("reverts if not called by owner", async function () { const [, , , notTheOwner] = await ethers.getSigners(); - await expect(this.enclave.connect(notTheOwner).enableComputationModule(this.mockComputationModule_address)) + const { computationModule } = this.requestParams; + await expect(this.enclave.connect(notTheOwner).enableComputationModule(computationModule)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if computation module is already enabled", async function () { - await expect(this.enclave.enableComputationModule(this.mockComputationModule_address)) + const { computationModule } = this.requestParams; + await expect(this.enclave.enableComputationModule(computationModule)) .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") - .withArgs(this.mockComputationModule_address); + .withArgs(computationModule); }); it("enables computation module correctly", async function () { - const enabled = await this.enclave.computationModules(this.mockComputationModule_address); + const { computationModule } = this.requestParams; + const enabled = await this.enclave.computationModules(computationModule); expect(enabled).to.be.true; }); it("returns true if computation module is enabled successfully", async function () { @@ -202,7 +200,8 @@ describe("Enclave", function () { describe("disableComputationModule()", function () { it("reverts if not called by owner", async function () { const [, , , notTheOwner] = await ethers.getSigners(); - await expect(this.enclave.connect(notTheOwner).disableComputationModule(this.mockComputationModule_address)) + const { computationModule } = this.requestParams; + await expect(this.enclave.connect(notTheOwner).disableComputationModule(computationModule)) .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); @@ -212,20 +211,23 @@ describe("Enclave", function () { .withArgs(AddressTwo); }); it("disables computation module correctly", async function () { - await this.enclave.disableComputationModule(this.mockComputationModule_address); + const { computationModule } = this.requestParams; + await this.enclave.disableComputationModule(computationModule); - const enabled = await this.enclave.computationModules(this.mockComputationModule_address); + const enabled = await this.enclave.computationModules(computationModule); expect(enabled).to.be.false; }); it("returns true if computation module is disabled successfully", async function () { - const result = await this.enclave.disableComputationModule.staticCall(this.mockComputationModule_address); + const { computationModule } = this.requestParams; + const result = await this.enclave.disableComputationModule.staticCall(computationModule); expect(result).to.be.true; }); it("emits ComputationModuleDisabled event", async function () { - await expect(this.enclave.disableComputationModule(this.mockComputationModule_address)) + const { computationModule } = this.requestParams; + await expect(this.enclave.disableComputationModule(computationModule)) .to.emit(this.enclave, "ComputationModuleDisabled") - .withArgs(this.mockComputationModule_address); + .withArgs(computationModule); }); }); diff --git a/packages/evm/test/fixtures/MockComputationModule.fixture.ts b/packages/evm/test/fixtures/MockComputationModule.fixture.ts index 3610de33..69dc901d 100644 --- a/packages/evm/test/fixtures/MockComputationModule.fixture.ts +++ b/packages/evm/test/fixtures/MockComputationModule.fixture.ts @@ -1,14 +1,9 @@ import { ethers } from "hardhat"; -import type { MockComputationModule } from "../../types/contracts/test/MockComputationModule"; -import type { MockComputationModule__factory } from "../../types/factories/contracts/test/MockComputationModule__factory"; +import { MockComputationModule__factory } from "../../types/factories/contracts/test/MockComputationModule__factory"; -export async function deployMockComputationModuleFixture() { - const MockComputationModule = (await ethers.getContractFactory( - "MockComputationModule", - )) as MockComputationModule__factory; - const mockComputationModule = (await MockComputationModule.deploy()) as MockComputationModule; - const mockComputationModule_address = await mockComputationModule.getAddress(); +export async function deployComputationModuleFixture() { + const deployment = await (await ethers.getContractFactory("MockComputationModule")).deploy(); - return { mockComputationModule, mockComputationModule_address }; + return MockComputationModule__factory.connect(await deployment.getAddress()); } From ecd83c1b1aa8c1ea106384421aa2605b7de3de2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 14:41:00 +0200 Subject: [PATCH 44/62] Simplify Fixture deployment --- .../test/fixtures/MockCypherNodeRegistry.fixture.ts | 11 +++-------- .../evm/test/fixtures/MockExecutionModule.fixture.ts | 9 +++------ .../evm/test/fixtures/MockInputValidator.fixture.ts | 10 +++------- .../evm/test/fixtures/MockOutputVerifier.fixture.ts | 10 +++------- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts index 89d710ba..8dab767c 100644 --- a/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts +++ b/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts @@ -1,14 +1,9 @@ import { ethers } from "hardhat"; -import { MockCypherNodeRegistry } from "../../types/contracts/test/MockCypherNodeRegistry"; import { MockCypherNodeRegistry__factory } from "../../types/factories/contracts/test/MockCypherNodeRegistry__factory"; -export async function deployMockCypherNodeRegistryFixture() { - const MockCypherNodeRegistry = (await ethers.getContractFactory( - "MockCypherNodeRegistry", - )) as MockCypherNodeRegistry__factory; - const mockCypherNodeRegistry = (await MockCypherNodeRegistry.deploy()) as MockCypherNodeRegistry; - const mockCypherNodeRegistry_address = await mockCypherNodeRegistry.getAddress(); +export async function deployCypherNodeRegistryFixture() { + const deployment = await (await ethers.getContractFactory("MockCypherNodeRegistry")).deploy(); - return { mockCypherNodeRegistry, mockCypherNodeRegistry_address }; + return MockCypherNodeRegistry__factory.connect(await deployment.getAddress()); } diff --git a/packages/evm/test/fixtures/MockExecutionModule.fixture.ts b/packages/evm/test/fixtures/MockExecutionModule.fixture.ts index 267f3316..56793f64 100644 --- a/packages/evm/test/fixtures/MockExecutionModule.fixture.ts +++ b/packages/evm/test/fixtures/MockExecutionModule.fixture.ts @@ -1,12 +1,9 @@ import { ethers } from "hardhat"; -import { MockExecutionModule } from "../../types/contracts/test/MockExecutionModule"; import { MockExecutionModule__factory } from "../../types/factories/contracts/test/MockExecutionModule__factory"; -export async function deployMockExecutionModuleFixture() { - const MockExecutionModule = (await ethers.getContractFactory("MockExecutionModule")) as MockExecutionModule__factory; - const mockExecutionModule = (await MockExecutionModule.deploy()) as MockExecutionModule; - const mockExecutionModule_address = await mockExecutionModule.getAddress(); +export async function deployExecutionModuleFixture() { + const deployment = await (await ethers.getContractFactory("MockExecutionModule")).deploy(); - return { mockExecutionModule, mockExecutionModule_address }; + return MockExecutionModule__factory.connect(await deployment.getAddress()); } diff --git a/packages/evm/test/fixtures/MockInputValidator.fixture.ts b/packages/evm/test/fixtures/MockInputValidator.fixture.ts index 096c86f1..21e8f70c 100644 --- a/packages/evm/test/fixtures/MockInputValidator.fixture.ts +++ b/packages/evm/test/fixtures/MockInputValidator.fixture.ts @@ -1,12 +1,8 @@ import { ethers } from "hardhat"; -import { MockInputValidator } from "../../types/contracts/test/MockInputValidator"; import { MockInputValidator__factory } from "../../types/factories/contracts/test/MockInputValidator__factory"; -export async function deployMockInputValidatorFixture() { - const MockInputValidator = (await ethers.getContractFactory("MockInputValidator")) as MockInputValidator__factory; - const mockInputValidator = (await MockInputValidator.deploy()) as MockInputValidator; - const mockInputValidator_address = await mockInputValidator.getAddress(); - - return { mockInputValidator, mockInputValidator_address }; +export async function deployInputValidatorFixture() { + const deployment = await (await ethers.getContractFactory("MockInputValidator")).deploy(); + return MockInputValidator__factory.connect(await deployment.getAddress()); } diff --git a/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts b/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts index a0615819..267c9555 100644 --- a/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts +++ b/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts @@ -1,12 +1,8 @@ import { ethers } from "hardhat"; -import { MockOutputVerifier } from "../../types/contracts/test/MockOutputVerifier"; import { MockOutputVerifier__factory } from "../../types/factories/contracts/test/MockOutputVerifier__factory"; -export async function deployMockOutputVerifierFixture() { - const MockOutputVerifier = (await ethers.getContractFactory("MockOutputVerifier")) as MockOutputVerifier__factory; - const mockOutputVerifier = (await MockOutputVerifier.deploy()) as MockOutputVerifier; - const mockOutputVerifier_address = await mockOutputVerifier.getAddress(); - - return { mockOutputVerifier, mockOutputVerifier_address }; +export async function deployOutputVerifierFixture() { + const deployment = await (await ethers.getContractFactory("MockComputationModule")).deploy(); + return MockOutputVerifier__factory.connect(await deployment.getAddress()); } From 14ae4f1ebae9438440a2e8024ed845a18bca842c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 16:00:32 +0200 Subject: [PATCH 45/62] Simplify main Enclave.fixture --- packages/evm/test/fixtures/Enclave.fixture.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index b2815e0a..36c61c04 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -6,19 +6,12 @@ import { Enclave__factory } from "../../types/factories/contracts/Enclave__facto export async function deployEnclaveFixture({ owner, registry, - maxDuration, + maxDuration = 60 * 60 * 24 * 30, }: { - owner?: SignerWithAddress; - registry?: SignerWithAddress; + owner: SignerWithAddress; + registry: string; maxDuration?: number; -} = {}) { - // Contracts are deployed using the first signer/account by default - const [account1, account2] = await ethers.getSigners(); - - owner = owner || account1; - registry = registry || account2; - maxDuration = maxDuration || 60 * 60 * 24 * 30; - +}) { const deployment = await (await ethers.getContractFactory("Enclave")).deploy(owner, registry, maxDuration); return Enclave__factory.connect(await deployment.getAddress(), owner); From 9910f3956ecb5ac303043d04395efe82963da01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 16:00:53 +0200 Subject: [PATCH 46/62] Move away from setup that uses multiple fixtures in a before each. Directly invoke the setup as fixture in each test - this is faster and cleaner --- packages/evm/test/Enclave.spec.ts | 571 +++++++++++++++++------------- 1 file changed, 316 insertions(+), 255 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 4380a0ee..d4cae1a4 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -1,166 +1,164 @@ import { loadFixture, time } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; +import { ZeroHash } from "ethers"; import { ethers } from "hardhat"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; import { deployComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; -import { deployMockCypherNodeRegistryFixture } from "./fixtures/MockCypherNodeRegistry.fixture"; -import { deployMockExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; -import { deployMockInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; -import { deployMockOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; +import { deployCypherNodeRegistryFixture } from "./fixtures/MockCypherNodeRegistry.fixture"; +import { deployExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; +import { deployInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; +import { deployOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const AddressTwo = "0x0000000000000000000000000000000000000002"; describe("Enclave", function () { - beforeEach(async function () { - const enclave = await loadFixture(deployEnclaveFixture); - this.enclave = enclave; - - const computationModule = await loadFixture(deployComputationModuleFixture); - - const { mockOutputVerifier, mockOutputVerifier_address } = await loadFixture(deployMockOutputVerifierFixture); - this.mockOutputVerifier = mockOutputVerifier; - this.mockOutputVerifier_address = mockOutputVerifier_address; - - const { mockCypherNodeRegistry, mockCypherNodeRegistry_address } = await loadFixture( - deployMockCypherNodeRegistryFixture, - ); - this.mockCypherNodeRegistry = mockCypherNodeRegistry; - this.mockCypherNodeRegistry_address = mockCypherNodeRegistry_address; - - const { mockExecutionModule, mockExecutionModule_address } = await loadFixture(deployMockExecutionModuleFixture); - this.mockExecutionModule = mockExecutionModule; - this.mockExecutionModule_address = mockExecutionModule_address; - - const { mockInputValidator, mockInputValidator_address } = await loadFixture(deployMockInputValidatorFixture); - this.mockInputValidator = mockInputValidator; - this.mockInputValidator_address = mockInputValidator_address; - - await this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address); - await this.enclave.enableComputationModule(await computationModule.getAddress()); - await this.enclave.enableExecutionModule(this.mockExecutionModule_address); - - this.requestParams = { - poolId: 1n, - threshold: [2n, 2n], - duration: time.duration.days(30), - computationModule: await computationModule.getAddress(), - cMParams: abiCoder.encode(["address"], [this.mockInputValidator_address]), - executionModule: this.mockExecutionModule_address, - eMParams: abiCoder.encode(["address"], [this.mockOutputVerifier_address]), + async function setup() { + const [owner, notTheOwner] = await ethers.getSigners(); + + const registry = await deployCypherNodeRegistryFixture(); + const computationModule = await deployComputationModuleFixture(); + const outputVerifier = await deployOutputVerifierFixture(); + const executionModule = await deployExecutionModuleFixture(); + const inputValidator = await deployInputValidatorFixture(); + + const enclave = await deployEnclaveFixture({ owner, registry: await registry.getAddress() }); + + await enclave.enableComputationModule(await computationModule.getAddress()); + await enclave.enableExecutionModule(await executionModule.getAddress()); + + return { + owner, + notTheOwner, + enclave, + mocks: { computationModule, outputVerifier, executionModule, inputValidator, registry }, + request: { + poolId: 1n, + threshold: [2, 2] as [number, number], + duration: time.duration.days(30), + computationModule: await computationModule.getAddress(), + cMParams: abiCoder.encode(["address"], [await inputValidator.getAddress()]), + executionModule: await executionModule.getAddress(), + eMParams: abiCoder.encode(["address"], [await outputVerifier.getAddress()]), + }, }; - }); + } describe("constructor / initialize()", function () { it("correctly sets owner", async function () { - const owner1 = await this.enclave.owner(); - const [, , , otherOwner, otherRegistry] = await ethers.getSigners(); - - const enclave = await deployEnclaveFixture({ owner: otherOwner, registry: otherRegistry }); - - // expect the owner to be the same as the one set in the fixture - expect(owner1).to.not.equal(otherOwner); - // expect the owner to be the same as the one set in the new deployment - expect(await enclave.owner()).to.equal(otherOwner); - expect(await enclave.cypherNodeRegistry()).to.equal(otherRegistry); + const [, , , someSigner] = await ethers.getSigners(); + const enclave = await deployEnclaveFixture({ owner: someSigner, registry: AddressTwo }); + expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); }); it("correctly sets cypherNodeRegistry address", async function () { - const cypherNodeRegistry = await this.enclave.cypherNodeRegistry(); - - expect(cypherNodeRegistry).to.equal(this.mockCypherNodeRegistry_address); + const [aSigner] = await ethers.getSigners(); + const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo }); + expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); }); it("correctly sets max duration", async function () { - const enclave = await deployEnclaveFixture({ maxDuration: 9876 }); + const [aSigner] = await ethers.getSigners(); + const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo, maxDuration: 9876 }); expect(await enclave.maxDuration()).to.equal(9876); }); }); describe("setMaxDuration()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); - await expect(this.enclave.connect(notTheOwner).setMaxDuration(1)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + const { enclave, notTheOwner } = await loadFixture(setup); + await expect(enclave.connect(notTheOwner).setMaxDuration(1)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("set max duration correctly", async function () { - await this.enclave.setMaxDuration(1); - - const maxDuration = await this.enclave.maxDuration(); - expect(maxDuration).to.equal(1); + const { enclave } = await loadFixture(setup); + await enclave.setMaxDuration(1); + expect(await enclave.maxDuration()).to.equal(1); }); it("returns true if max duration is set successfully", async function () { - const result = await this.enclave.setMaxDuration.staticCall(1); - + const { enclave } = await loadFixture(setup); + const result = await enclave.setMaxDuration.staticCall(1); expect(result).to.be.true; }); it("emits MaxDurationSet event", async function () { - await expect(this.enclave.setMaxDuration(1)).to.emit(this.enclave, "MaxDurationSet").withArgs(1); + const { enclave } = await loadFixture(setup); + await expect(enclave.setMaxDuration(1)).to.emit(enclave, "MaxDurationSet").withArgs(1); }); }); describe("setCypherNodeRegistry()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); + const { enclave, notTheOwner } = await loadFixture(setup); - await expect(this.enclave.connect(notTheOwner).setCypherNodeRegistry(AddressTwo)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + await expect(enclave.connect(notTheOwner).setCypherNodeRegistry(AddressTwo)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if given address(0)", async function () { - await expect(this.enclave.setCypherNodeRegistry(ethers.ZeroAddress)) - .to.be.revertedWithCustomError(this.enclave, "InvalidCypherNodeRegistry") + const { enclave } = await loadFixture(setup); + await expect(enclave.setCypherNodeRegistry(ethers.ZeroAddress)) + .to.be.revertedWithCustomError(enclave, "InvalidCypherNodeRegistry") .withArgs(ethers.ZeroAddress); }); it("reverts if given address is the same as the current cypherNodeRegistry", async function () { - await expect(this.enclave.setCypherNodeRegistry(this.mockCypherNodeRegistry_address)) - .to.be.revertedWithCustomError(this.enclave, "InvalidCypherNodeRegistry") - .withArgs(this.mockCypherNodeRegistry_address); + const { + enclave, + mocks: { registry }, + } = await loadFixture(setup); + await expect(enclave.setCypherNodeRegistry(registry)) + .to.be.revertedWithCustomError(enclave, "InvalidCypherNodeRegistry") + .withArgs(registry); }); it("sets cypherNodeRegistry correctly", async function () { - expect(await this.enclave.cypherNodeRegistry()).to.not.equal(AddressTwo); - - await this.enclave.setCypherNodeRegistry(AddressTwo); + const { enclave } = await loadFixture(setup); - expect(await this.enclave.cypherNodeRegistry()).to.equal(AddressTwo); + expect(await enclave.cypherNodeRegistry()).to.not.equal(AddressTwo); + await enclave.setCypherNodeRegistry(AddressTwo); + expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); }); it("returns true if cypherNodeRegistry is set successfully", async function () { - const result = await this.enclave.setCypherNodeRegistry.staticCall(AddressTwo); + const { enclave } = await loadFixture(setup); + const result = await enclave.setCypherNodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits CypherNodeRegistrySet event", async function () { - await expect(this.enclave.setCypherNodeRegistry(AddressTwo)) - .to.emit(this.enclave, "CypherNodeRegistrySet") + const { enclave } = await loadFixture(setup); + + await expect(enclave.setCypherNodeRegistry(AddressTwo)) + .to.emit(enclave, "CypherNodeRegistrySet") .withArgs(AddressTwo); }); }); describe("getE3()", function () { it("reverts if E3 does not exist", async function () { - await expect(this.enclave.getE3(1)).to.be.revertedWithCustomError(this.enclave, "E3DoesNotExist").withArgs(1); + const { enclave } = await loadFixture(setup); + + await expect(enclave.getE3(1)).to.be.revertedWithCustomError(enclave, "E3DoesNotExist").withArgs(1); }); it("returns correct E3 details", async function () { - await this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + const { enclave, request } = await loadFixture(setup); + await enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ); - const e3 = await this.enclave.getE3(0); + const e3 = await enclave.getE3(0); - expect(e3.threshold).to.deep.equal(this.requestParams.threshold); + expect(e3.threshold).to.deep.equal(request.threshold); expect(e3.expiration).to.equal(0n); - expect(e3.computationModule).to.equal(this.requestParams.computationModule); - expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], this.requestParams.cMParams)[0]); - expect(e3.executionModule).to.equal(this.requestParams.executionModule); - expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], this.requestParams.eMParams)[0]); + expect(e3.computationModule).to.equal(request.computationModule); + expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], request.cMParams)[0]); + expect(e3.executionModule).to.equal(request.executionModule); + expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], request.eMParams)[0]); expect(e3.committeePublicKey).to.equal("0x"); expect(e3.ciphertextOutput).to.equal("0x"); expect(e3.plaintextOutput).to.equal("0x"); @@ -169,314 +167,377 @@ describe("Enclave", function () { describe("enableComputationModule()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); - const { computationModule } = this.requestParams; - await expect(this.enclave.connect(notTheOwner).enableComputationModule(computationModule)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + const { + notTheOwner, + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + + await expect(enclave.connect(notTheOwner).enableComputationModule(computationModule)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if computation module is already enabled", async function () { - const { computationModule } = this.requestParams; - await expect(this.enclave.enableComputationModule(computationModule)) - .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") + const { + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + + await expect(enclave.enableComputationModule(computationModule)) + .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") .withArgs(computationModule); }); it("enables computation module correctly", async function () { - const { computationModule } = this.requestParams; - const enabled = await this.enclave.computationModules(computationModule); + const { + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + const enabled = await enclave.computationModules(computationModule); expect(enabled).to.be.true; }); it("returns true if computation module is enabled successfully", async function () { - const result = await this.enclave.enableComputationModule.staticCall(AddressTwo); + const { enclave } = await loadFixture(setup); + const result = await enclave.enableComputationModule.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits ComputationModuleEnabled event", async function () { - await expect(this.enclave.enableComputationModule(AddressTwo)) - .to.emit(this.enclave, "ComputationModuleEnabled") + const { enclave } = await loadFixture(setup); + await expect(enclave.enableComputationModule(AddressTwo)) + .to.emit(enclave, "ComputationModuleEnabled") .withArgs(AddressTwo); }); }); describe("disableComputationModule()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); - const { computationModule } = this.requestParams; - await expect(this.enclave.connect(notTheOwner).disableComputationModule(computationModule)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + const { + notTheOwner, + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + await expect(enclave.connect(notTheOwner).disableComputationModule(computationModule)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if computation module is not enabled", async function () { - await expect(this.enclave.disableComputationModule(AddressTwo)) - .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + const { enclave } = await loadFixture(setup); + await expect(enclave.disableComputationModule(AddressTwo)) + .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); it("disables computation module correctly", async function () { - const { computationModule } = this.requestParams; - await this.enclave.disableComputationModule(computationModule); + const { + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + await enclave.disableComputationModule(computationModule); - const enabled = await this.enclave.computationModules(computationModule); + const enabled = await enclave.computationModules(computationModule); expect(enabled).to.be.false; }); it("returns true if computation module is disabled successfully", async function () { - const { computationModule } = this.requestParams; - const result = await this.enclave.disableComputationModule.staticCall(computationModule); + const { + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + const result = await enclave.disableComputationModule.staticCall(computationModule); expect(result).to.be.true; }); it("emits ComputationModuleDisabled event", async function () { - const { computationModule } = this.requestParams; - await expect(this.enclave.disableComputationModule(computationModule)) - .to.emit(this.enclave, "ComputationModuleDisabled") + const { + enclave, + mocks: { computationModule }, + } = await loadFixture(setup); + await expect(enclave.disableComputationModule(computationModule)) + .to.emit(enclave, "ComputationModuleDisabled") .withArgs(computationModule); }); }); describe("enableExecutionModule()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); - await expect(this.enclave.connect(notTheOwner).enableExecutionModule(this.mockExecutionModule_address)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + const { notTheOwner, enclave } = await loadFixture(setup); + await expect(enclave.connect(notTheOwner).enableExecutionModule(AddressTwo)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner.address); }); it("reverts if execution module is already enabled", async function () { - await expect(this.enclave.enableExecutionModule(this.mockExecutionModule_address)) - .to.be.revertedWithCustomError(this.enclave, "ModuleAlreadyEnabled") - .withArgs(this.mockExecutionModule_address); + const { + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); + await expect(enclave.enableExecutionModule(executionModule)) + .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") + .withArgs(executionModule); }); it("enables execution module correctly", async function () { - const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); + const { + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); + const enabled = await enclave.executionModules(executionModule); expect(enabled).to.be.true; }); it("returns true if execution module is enabled successfully", async function () { - const result = await this.enclave.enableExecutionModule.staticCall(AddressTwo); + const { enclave } = await loadFixture(setup); + const result = await enclave.enableExecutionModule.staticCall(AddressTwo); expect(result).to.be.true; }); it("emits ExecutionModuleEnabled event", async function () { - await expect(this.enclave.enableExecutionModule(AddressTwo)) - .to.emit(this.enclave, "ExecutionModuleEnabled") + const { enclave } = await loadFixture(setup); + await expect(enclave.enableExecutionModule(AddressTwo)) + .to.emit(enclave, "ExecutionModuleEnabled") .withArgs(AddressTwo); }); }); describe("disableExecutionModule()", function () { it("reverts if not called by owner", async function () { - const [, , , notTheOwner] = await ethers.getSigners(); - - await expect(this.enclave.connect(notTheOwner).disableExecutionModule(this.mockExecutionModule_address)) - .to.be.revertedWithCustomError(this.enclave, "OwnableUnauthorizedAccount") + const { + notTheOwner, + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); + + await expect(enclave.connect(notTheOwner).disableExecutionModule(executionModule)) + .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if execution module is not enabled", async function () { - await expect(this.enclave.disableExecutionModule(AddressTwo)) - .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + const { enclave } = await loadFixture(setup); + await expect(enclave.disableExecutionModule(AddressTwo)) + .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); it("disables execution module correctly", async function () { - await this.enclave.disableExecutionModule(this.mockExecutionModule_address); + const { + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); - const enabled = await this.enclave.executionModules(this.mockExecutionModule_address); - expect(enabled).to.be.false; + expect(await enclave.executionModules(executionModule)).to.be.true; + await enclave.disableExecutionModule(executionModule); + expect(await enclave.executionModules(executionModule)).to.be.false; }); it("returns true if execution module is disabled successfully", async function () { - const result = await this.enclave.disableExecutionModule.staticCall(this.mockExecutionModule_address); + const { + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); + const result = await enclave.disableExecutionModule.staticCall(executionModule); expect(result).to.be.true; }); it("emits ExecutionModuleDisabled event", async function () { - await expect(this.enclave.disableExecutionModule(this.mockExecutionModule_address)) - .to.emit(this.enclave, "ExecutionModuleDisabled") - .withArgs(this.mockExecutionModule_address); + const { + enclave, + mocks: { executionModule }, + } = await loadFixture(setup); + + await expect(enclave.disableExecutionModule(executionModule)) + .to.emit(enclave, "ExecutionModuleDisabled") + .withArgs(executionModule); }); }); describe("request()", function () { it("reverts if msg.value is 0", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, ), - ).to.be.revertedWithCustomError(this.enclave, "PaymentRequired"); + ).to.be.revertedWithCustomError(enclave, "PaymentRequired"); }); it("reverts if threshold is 0", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, + enclave.request( + request.poolId, [0, 2], - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidThreshold"); + ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); it("reverts if threshold is greater than number", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, + enclave.request( + request.poolId, [3, 2], - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidThreshold"); + ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); it("reverts if duration is 0", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, + enclave.request( + request.poolId, + request.threshold, 0, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidDuration"); + ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); it("reverts if duration is greater than maxDuration", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, + enclave.request( + request.poolId, + request.threshold, time.duration.days(31), - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidDuration"); + ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); it("reverts if computation module is not enabled", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, + enclave.request( + request.poolId, + request.threshold, + request.duration, ethers.ZeroAddress, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), ) - .to.be.revertedWithCustomError(this.enclave, "ComputationModuleNotAllowed") + .to.be.revertedWithCustomError(enclave, "ComputationModuleNotAllowed") .withArgs(ethers.ZeroAddress); }); it("reverts if execution module is not enabled", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, + enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, ethers.ZeroAddress, - this.requestParams.eMParams, + request.eMParams, { value: 10 }, ), ) - .to.be.revertedWithCustomError(this.enclave, "ModuleNotEnabled") + .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(ethers.ZeroAddress); }); it("reverts if input computation module does not return input validator address", async function () { - const zeroInput = abiCoder.encode(["address"], [ethers.ZeroAddress]); + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - zeroInput, - this.requestParams.executionModule, - this.requestParams.eMParams, + enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + ZeroHash, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidComputation"); + ).to.be.revertedWithCustomError(enclave, "InvalidComputation"); }); it("reverts if input execution module does not return output verifier address", async function () { - const zeroInput = abiCoder.encode(["address"], [ethers.ZeroAddress]); - + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - zeroInput, + enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + ZeroHash, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "InvalidExecutionModuleSetup"); + ).to.be.revertedWithCustomError(enclave, "InvalidExecutionModuleSetup"); }); it("reverts if committee selection fails", async function () { + const { enclave, request } = await loadFixture(setup); await expect( - this.enclave.request( + enclave.request( 0, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ), - ).to.be.revertedWithCustomError(this.enclave, "CommitteeSelectionFailed"); + ).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); }); it("instantiates a new E3", async function () { - await this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + const { enclave, request } = await loadFixture(setup); + await enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ); - const e3 = await this.enclave.getE3(0); + const e3 = await enclave.getE3(0); - expect(e3.threshold).to.deep.equal(this.requestParams.threshold); + expect(e3.threshold).to.deep.equal(request.threshold); expect(e3.expiration).to.equal(0n); - expect(e3.computationModule).to.equal(this.requestParams.computationModule); - expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], this.requestParams.cMParams)[0]); - expect(e3.executionModule).to.equal(this.requestParams.executionModule); - expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], this.requestParams.eMParams)[0]); + expect(e3.computationModule).to.equal(request.computationModule); + expect(e3.inputValidator).to.equal(abiCoder.decode(["address"], request.cMParams)[0]); + expect(e3.executionModule).to.equal(request.executionModule); + expect(e3.outputVerifier).to.equal(abiCoder.decode(["address"], request.eMParams)[0]); expect(e3.committeePublicKey).to.equal("0x"); expect(e3.ciphertextOutput).to.equal("0x"); expect(e3.plaintextOutput).to.equal("0x"); }); it("emits E3Requested event", async function () { - const tx = await this.enclave.request( - this.requestParams.poolId, - this.requestParams.threshold, - this.requestParams.duration, - this.requestParams.computationModule, - this.requestParams.cMParams, - this.requestParams.executionModule, - this.requestParams.eMParams, + const { enclave, request } = await loadFixture(setup); + const tx = await enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, { value: 10 }, ); - const e3 = await this.enclave.getE3(0); + const e3 = await enclave.getE3(0); await expect(tx) - .to.emit(this.enclave, "E3Requested") - .withArgs(0, e3, 1, this.requestParams.computationModule, this.requestParams.executionModule); + .to.emit(enclave, "E3Requested") + .withArgs(0, e3, 1, request.computationModule, request.executionModule); }); }); From d54a1ce0b0f266bd9cdbf8f013e03d2e16cfe550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 17:12:15 +0200 Subject: [PATCH 47/62] Add test for activate: reversts when e3 does not exist --- packages/evm/contracts/test/MockCypherNodeRegistry.sol | 2 +- packages/evm/test/Enclave.spec.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/evm/contracts/test/MockCypherNodeRegistry.sol b/packages/evm/contracts/test/MockCypherNodeRegistry.sol index e3f921e6..6b4eef3e 100644 --- a/packages/evm/contracts/test/MockCypherNodeRegistry.sol +++ b/packages/evm/contracts/test/MockCypherNodeRegistry.sol @@ -13,6 +13,6 @@ contract MockCypherNodeRegistry is ICypherNodeRegistry { } function getCommitteePublicKey(uint256 e3Id) external pure returns (bytes memory) { - return new bytes(e3Id); + return abi.encodePacked(keccak256(abi.encode(e3Id))); } } diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index d4cae1a4..8320207c 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -542,7 +542,11 @@ describe("Enclave", function () { }); describe("activate()", function () { - it("reverts if E3 does not exist"); + it("reverts if E3 does not exist", async function () { + const { enclave } = await loadFixture(setup); + + await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3DoesNotExist").withArgs(0); + }); it("reverts if E3 has already been activated"); it("reverts if cypherNodeRegistry does not return a public key"); it("sets committeePublicKey correctly"); From 90ccbbad5712d6527ea0497980b35f5eaf30b88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Mon, 3 Jun 2024 17:24:10 +0200 Subject: [PATCH 48/62] add test fix bug: set expiration in storage when activating e3 --- packages/evm/contracts/Enclave.sol | 10 +++++++--- packages/evm/test/Enclave.spec.ts | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index fadaecde..864c56eb 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -137,16 +137,20 @@ contract Enclave is IEnclave, OwnableUpgradeable { } function activate(uint256 e3Id) external returns (bool success) { + // Note: we could load this into a storage pointer, and do the sets there + // Requires a mew internal _getter that returns storage E3 memory e3 = getE3(e3Id); require(e3.expiration == 0, E3AlreadyActivated(e3Id)); - e3.expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. bytes memory committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); - success = committeePublicKey.length > 0; - require(success, CommitteeSelectionFailed()); + require(committeePublicKey.length > 0, CommitteeSelectionFailed()); + + e3s[e3Id].expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. e3s[e3Id].committeePublicKey = committeePublicKey; emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey); + + return true; } function publishInput(uint256 e3Id, bytes memory data) external returns (bool success) { diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 8320207c..e0c52fa4 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -547,7 +547,24 @@ describe("Enclave", function () { await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3DoesNotExist").withArgs(0); }); - it("reverts if E3 has already been activated"); + it("reverts if E3 has already been activated", async function () { + const { enclave, request } = await loadFixture(setup); + + await enclave.request( + request.poolId, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, + { value: 10 }, + ); + + await expect(enclave.getE3(0)).to.not.be.reverted; + await expect(enclave.activate(0)).to.not.be.reverted; + await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3AlreadyActivated").withArgs(0); + }); it("reverts if cypherNodeRegistry does not return a public key"); it("sets committeePublicKey correctly"); it("returns true if E3 is activated successfully"); From 39e88eb94b34fdf06a8aeabbddfd9fa837459921 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 08:45:14 +1000 Subject: [PATCH 49/62] rename publishDecryptedOutput to publishPlaintextOutput --- packages/evm/contracts/Enclave.sol | 2 +- packages/evm/contracts/interfaces/IEnclave.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 864c56eb..ab3ce5cd 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -175,7 +175,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit CiphertextOutputPublished(e3Id, output); } - function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishPlaintextOutput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index cbcde5a6..c9567900 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -118,13 +118,13 @@ interface IEnclave { /// @return success True if the output was successfully published. function publishCiphertextOutput(uint256 e3Id, bytes memory data) external returns (bool success); - /// @notice This function should be called to decrypt the output of an Encrypted Execution Environment (E3). + /// @notice This function should be called to publish the plaintext output of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the output has not been published. /// @dev This function MUST emit the PlaintextOutputPublished event. /// @param e3Id ID of the E3. /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. - function publishDecryptedOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishPlaintextOutput(uint256 e3Id, bytes memory data) external returns (bool success); //////////////////////////////////////////////////////////// // // From bbcc841a013679363213f9cede122073687532e5 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 10:20:29 +1000 Subject: [PATCH 50/62] change pool to address, rather than uint256 --- packages/evm/contracts/Enclave.sol | 6 ++-- .../interfaces/ICypherNodeRegistry.sol | 20 +++++++++++- .../evm/contracts/interfaces/IEnclave.sol | 8 ++--- .../contracts/registry/CypherNodeOwnable.sol | 15 +++++++++ .../registry/cypherNodeRegistryBase.sol | 14 ++++++++ .../contracts/test/MockCypherNodeRegistry.sol | 4 +-- packages/evm/test/Enclave.spec.ts | 32 +++++++++---------- 7 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 packages/evm/contracts/registry/CypherNodeOwnable.sol create mode 100644 packages/evm/contracts/registry/cypherNodeRegistryBase.sol diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index ab3ce5cd..d9cca8e3 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -89,7 +89,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// function request( - uint256 poolId, + address pool, uint32[2] calldata threshold, uint256 duration, // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are published before the request is made? This kind of assumes the cypher nodes have already been selected and generated a shared secret. IComputationModule computationModule, @@ -130,10 +130,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { }); e3s[e3Id] = e3; - require(cypherNodeRegistry.selectCommittee(e3Id, poolId, threshold), CommitteeSelectionFailed()); + require(cypherNodeRegistry.selectCommittee(e3Id, pool, threshold), CommitteeSelectionFailed()); // TODO: validate that the selected pool accepts both the computation and execution modules. - emit E3Requested(e3Id, e3s[e3Id], poolId, computationModule, executionModule); + emit E3Requested(e3Id, e3s[e3Id], pool, computationModule, executionModule); } function activate(uint256 e3Id) external returns (bool success) { diff --git a/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol index 323a7a7b..4a865abf 100644 --- a/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol @@ -2,6 +2,24 @@ pragma solidity >=0.8.26; interface ICypherNodeRegistry { + /// @notice This event MUST be emitted when a node is added to the registry. + /// @param nodeId ID of the node. + /// @param node Address of the node. + event NodeAdded(uint256 indexed nodeId, address indexed node); + + /// @notice This event MUST be emitted when a node is removed from the registry. + /// @param nodeId ID of the node. + /// @param node Address of the node. + event NodeRemoved(uint256 indexed nodeId, address indexed node); + + /// @notice This event MUST be emitted when a pool is added to the registry. + /// @param poolId ID of the pool. + event PoolAdded(address indexed poolId); + + /// @notice This event MUST be emitted when a pool is removed from the registry. + /// @param poolId ID of the pool. + event PoolRemoved(address indexed poolId); + /// @notice This function should be called by the Enclave contract to select a node committee. /// @param e3Id ID of the E3 for which to select the committee. /// @param poolId ID of the pool of nodes from which to select the committee. @@ -9,7 +27,7 @@ interface ICypherNodeRegistry { /// @return success True if committee selection was successfully initiated. function selectCommittee( uint256 e3Id, - uint256 poolId, + address poolId, uint32[2] calldata threshold ) external returns (bool success); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index c9567900..d9ec4d1b 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -13,13 +13,13 @@ interface IEnclave { /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested. /// @param e3Id ID of the E3. /// @param e3 Details of the E3. - /// @param poolId ID of the pool of nodes from which the Cypher Node committee was selected. + /// @param pool Address of the pool of nodes from which the Cypher Node committee was selected. /// @param computationModule Address of the Computation module selected. /// @param executionModule Address of the execution module selected. event E3Requested( uint256 e3Id, E3 e3, - uint256 indexed poolId, + address indexed pool, IComputationModule indexed computationModule, IExecutionModule indexed executionModule ); @@ -77,7 +77,7 @@ interface IEnclave { /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @dev This function MUST emit the E3Requested event. - /// @param poolId ID of the pool of nodes from which to select the committee. + /// @param pool ID of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @param duration The duration of the computation in seconds. /// @param computationModule Address of the computation module. @@ -87,7 +87,7 @@ interface IEnclave { /// @return e3Id ID of the E3. /// @return e3 The E3 struct. function request( - uint256 poolId, + address pool, uint32[2] calldata threshold, uint256 duration, IComputationModule computationModule, diff --git a/packages/evm/contracts/registry/CypherNodeOwnable.sol b/packages/evm/contracts/registry/CypherNodeOwnable.sol new file mode 100644 index 00000000..3700f41d --- /dev/null +++ b/packages/evm/contracts/registry/CypherNodeOwnable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +abstract contract CypherNodeRegistryOwnable is ICypherNodeRegistry { + function selectCommittee( + uint256 e3Id, + address poolId, + uint32[2] calldata threshold + ) external returns (bool success) {} + + function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey) {} +} diff --git a/packages/evm/contracts/registry/cypherNodeRegistryBase.sol b/packages/evm/contracts/registry/cypherNodeRegistryBase.sol new file mode 100644 index 00000000..99743ad8 --- /dev/null +++ b/packages/evm/contracts/registry/cypherNodeRegistryBase.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; + +abstract contract CypherNodeRegistryBase is ICypherNodeRegistry { + function selectCommittee( + uint256 e3Id, + uint256 poolId, + uint32[2] calldata threshold + ) external returns (bool success) {} + + function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey) {} +} diff --git a/packages/evm/contracts/test/MockCypherNodeRegistry.sol b/packages/evm/contracts/test/MockCypherNodeRegistry.sol index 6b4eef3e..d2692ad8 100644 --- a/packages/evm/contracts/test/MockCypherNodeRegistry.sol +++ b/packages/evm/contracts/test/MockCypherNodeRegistry.sol @@ -4,8 +4,8 @@ pragma solidity >=0.8.26; import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; contract MockCypherNodeRegistry is ICypherNodeRegistry { - function selectCommittee(uint256, uint256 poolId, uint32[2] calldata) external pure returns (bool success) { - if (poolId == 0) { + function selectCommittee(uint256, address pool, uint32[2] calldata) external pure returns (bool success) { + if (pool == address(2)) { success = false; } else { success = true; diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index e0c52fa4..34eab536 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -34,7 +34,7 @@ describe("Enclave", function () { enclave, mocks: { computationModule, outputVerifier, executionModule, inputValidator, registry }, request: { - poolId: 1n, + pool: ethers.ZeroAddress, threshold: [2, 2] as [number, number], duration: time.duration.days(30), computationModule: await computationModule.getAddress(), @@ -142,7 +142,7 @@ describe("Enclave", function () { it("returns correct E3 details", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -347,7 +347,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -361,7 +361,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, [0, 2], request.duration, request.computationModule, @@ -376,7 +376,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, [3, 2], request.duration, request.computationModule, @@ -391,7 +391,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, 0, request.computationModule, @@ -406,7 +406,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, time.duration.days(31), request.computationModule, @@ -421,7 +421,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, ethers.ZeroAddress, @@ -438,7 +438,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -456,7 +456,7 @@ describe("Enclave", function () { await expect( enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -471,7 +471,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -486,7 +486,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - 0, + AddressTwo, request.threshold, request.duration, request.computationModule, @@ -500,7 +500,7 @@ describe("Enclave", function () { it("instantiates a new E3", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -524,7 +524,7 @@ describe("Enclave", function () { it("emits E3Requested event", async function () { const { enclave, request } = await loadFixture(setup); const tx = await enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, @@ -537,7 +537,7 @@ describe("Enclave", function () { await expect(tx) .to.emit(enclave, "E3Requested") - .withArgs(0, e3, 1, request.computationModule, request.executionModule); + .withArgs(0, e3, request.pool, request.computationModule, request.executionModule); }); }); @@ -551,7 +551,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await enclave.request( - request.poolId, + request.pool, request.threshold, request.duration, request.computationModule, From a6a39b3c085d632155d14668811d0850017b11cc Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 10:58:57 +1000 Subject: [PATCH 51/62] add TODO --- packages/evm/contracts/Enclave.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index d9cca8e3..a38fde40 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -89,7 +89,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// function request( - address pool, + address pool, // TODO: should we allow for multiple pools? uint32[2] calldata threshold, uint256 duration, // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are published before the request is made? This kind of assumes the cypher nodes have already been selected and generated a shared secret. IComputationModule computationModule, From c4a762397b1305ac2d0be56055bc3ff9c09ad57d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 11:36:41 +1000 Subject: [PATCH 52/62] delete registry directory --- .../evm/contracts/registry/CypherNodeOwnable.sol | 15 --------------- .../contracts/registry/cypherNodeRegistryBase.sol | 14 -------------- 2 files changed, 29 deletions(-) delete mode 100644 packages/evm/contracts/registry/CypherNodeOwnable.sol delete mode 100644 packages/evm/contracts/registry/cypherNodeRegistryBase.sol diff --git a/packages/evm/contracts/registry/CypherNodeOwnable.sol b/packages/evm/contracts/registry/CypherNodeOwnable.sol deleted file mode 100644 index 3700f41d..00000000 --- a/packages/evm/contracts/registry/CypherNodeOwnable.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; - -import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -abstract contract CypherNodeRegistryOwnable is ICypherNodeRegistry { - function selectCommittee( - uint256 e3Id, - address poolId, - uint32[2] calldata threshold - ) external returns (bool success) {} - - function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey) {} -} diff --git a/packages/evm/contracts/registry/cypherNodeRegistryBase.sol b/packages/evm/contracts/registry/cypherNodeRegistryBase.sol deleted file mode 100644 index 99743ad8..00000000 --- a/packages/evm/contracts/registry/cypherNodeRegistryBase.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; - -import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; - -abstract contract CypherNodeRegistryBase is ICypherNodeRegistry { - function selectCommittee( - uint256 e3Id, - uint256 poolId, - uint32[2] calldata threshold - ) external returns (bool success) {} - - function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey) {} -} From 404a4ef258d98afa82df0766a406da307fef2397 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 16:17:47 +1000 Subject: [PATCH 53/62] CypherNode --> Cyphernode --- packages/evm/contracts/Enclave.sol | 28 ++++++------ ...deRegistry.sol => ICyphernodeRegistry.sol} | 2 +- .../evm/contracts/interfaces/IEnclave.sol | 6 +-- ...egistry.sol => MockCyphernodeRegistry.sol} | 4 +- packages/evm/test/Enclave.spec.ts | 44 +++++++++---------- .../MockCypherNodeRegistry.fixture.ts | 8 ++-- 6 files changed, 46 insertions(+), 46 deletions(-) rename packages/evm/contracts/interfaces/{ICypherNodeRegistry.sol => ICyphernodeRegistry.sol} (98%) rename packages/evm/contracts/test/{MockCypherNodeRegistry.sol => MockCyphernodeRegistry.sol} (79%) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index a38fde40..acc6e678 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.26; import { IEnclave, E3, IComputationModule, IExecutionModule } from "./interfaces/IEnclave.sol"; -import { ICypherNodeRegistry } from "./interfaces/ICypherNodeRegistry.sol"; +import { ICyphernodeRegistry } from "./interfaces/ICyphernodeRegistry.sol"; import { IInputValidator } from "./interfaces/IInputValidator.sol"; import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -14,7 +14,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// - ICypherNodeRegistry public cypherNodeRegistry; // TODO: add a setter function. + ICyphernodeRegistry public cyphernodeRegistry; // TODO: add a setter function. uint256 public maxDuration; // TODO: add a setter function. uint256 public nexte3Id; // ID of the next E3. uint256 public requests; // total number of requests made to Enclave. @@ -47,7 +47,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); error InvalidExecutionModuleSetup(); - error InvalidCypherNodeRegistry(ICypherNodeRegistry cypherNodeRegistry); + error InvalidCyphernodeRegistry(ICyphernodeRegistry cyphernodeRegistry); error InvalidInput(); error InvalidDuration(uint256 duration); error InvalidOutput(); @@ -65,20 +65,20 @@ contract Enclave is IEnclave, OwnableUpgradeable { /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds - constructor(address _owner, ICypherNodeRegistry _cypherNodeRegistry, uint256 _maxDuration) { - initialize(_owner, _cypherNodeRegistry, _maxDuration); + constructor(address _owner, ICyphernodeRegistry _cyphernodeRegistry, uint256 _maxDuration) { + initialize(_owner, _cyphernodeRegistry, _maxDuration); } /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds function initialize( address _owner, - ICypherNodeRegistry _cypherNodeRegistry, + ICyphernodeRegistry _cyphernodeRegistry, uint256 _maxDuration ) public initializer { __Ownable_init(msg.sender); setMaxDuration(_maxDuration); - setCypherNodeRegistry(_cypherNodeRegistry); + setCyphernodeRegistry(_cyphernodeRegistry); if (_owner != owner()) transferOwnership(_owner); } @@ -130,7 +130,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { }); e3s[e3Id] = e3; - require(cypherNodeRegistry.selectCommittee(e3Id, pool, threshold), CommitteeSelectionFailed()); + require(cyphernodeRegistry.selectCommittee(e3Id, pool, threshold), CommitteeSelectionFailed()); // TODO: validate that the selected pool accepts both the computation and execution modules. emit E3Requested(e3Id, e3s[e3Id], pool, computationModule, executionModule); @@ -142,7 +142,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { E3 memory e3 = getE3(e3Id); require(e3.expiration == 0, E3AlreadyActivated(e3Id)); - bytes memory committeePublicKey = cypherNodeRegistry.getCommitteePublicKey(e3Id); + bytes memory committeePublicKey = cyphernodeRegistry.getCommitteePublicKey(e3Id); require(committeePublicKey.length > 0, CommitteeSelectionFailed()); e3s[e3Id].expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. @@ -199,14 +199,14 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit MaxDurationSet(_maxDuration); } - function setCypherNodeRegistry(ICypherNodeRegistry _cypherNodeRegistry) public onlyOwner returns (bool success) { + function setCyphernodeRegistry(ICyphernodeRegistry _cyphernodeRegistry) public onlyOwner returns (bool success) { require( - address(_cypherNodeRegistry) != address(0) && _cypherNodeRegistry != cypherNodeRegistry, - InvalidCypherNodeRegistry(_cypherNodeRegistry) + address(_cyphernodeRegistry) != address(0) && _cyphernodeRegistry != cyphernodeRegistry, + InvalidCyphernodeRegistry(_cyphernodeRegistry) ); - cypherNodeRegistry = _cypherNodeRegistry; + cyphernodeRegistry = _cyphernodeRegistry; success = true; - emit CypherNodeRegistrySet(address(_cypherNodeRegistry)); + emit CyphernodeRegistrySet(address(_cyphernodeRegistry)); } function enableComputationModule(IComputationModule computationModule) public onlyOwner returns (bool success) { diff --git a/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol similarity index 98% rename from packages/evm/contracts/interfaces/ICypherNodeRegistry.sol rename to packages/evm/contracts/interfaces/ICyphernodeRegistry.sol index 4a865abf..6a99ba46 100644 --- a/packages/evm/contracts/interfaces/ICypherNodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -interface ICypherNodeRegistry { +interface ICyphernodeRegistry { /// @notice This event MUST be emitted when a node is added to the registry. /// @param nodeId ID of the node. /// @param node Address of the node. diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index d9ec4d1b..40b3c237 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -49,9 +49,9 @@ interface IEnclave { /// @param maxDuration The maximum duration of a computation in seconds. event MaxDurationSet(uint256 maxDuration); - /// @notice This event MUST be emitted any time the CypherNodeRegistry is set. - /// @param cypherNodeRegistry The address of the CypherNodeRegistry contract. - event CypherNodeRegistrySet(address cypherNodeRegistry); + /// @notice This event MUST be emitted any time the CyphernodeRegistry is set. + /// @param cyphernodeRegistry The address of the CyphernodeRegistry contract. + event CyphernodeRegistrySet(address cyphernodeRegistry); /// @notice This event MUST be emitted any time a computation module is enabled. /// @param computationModule The address of the computation module. diff --git a/packages/evm/contracts/test/MockCypherNodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol similarity index 79% rename from packages/evm/contracts/test/MockCypherNodeRegistry.sol rename to packages/evm/contracts/test/MockCyphernodeRegistry.sol index d2692ad8..44151eac 100644 --- a/packages/evm/contracts/test/MockCypherNodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { ICypherNodeRegistry } from "../interfaces/ICypherNodeRegistry.sol"; +import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; -contract MockCypherNodeRegistry is ICypherNodeRegistry { +contract MockCyphernodeRegistry is ICyphernodeRegistry { function selectCommittee(uint256, address pool, uint32[2] calldata) external pure returns (bool success) { if (pool == address(2)) { success = false; diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 34eab536..f4323ed9 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -5,7 +5,7 @@ import { ethers } from "hardhat"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; import { deployComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; -import { deployCypherNodeRegistryFixture } from "./fixtures/MockCypherNodeRegistry.fixture"; +import { deployCyphernodeRegistryFixture } from "./fixtures/MockCyphernodeRegistry.fixture"; import { deployExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; import { deployInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; import { deployOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; @@ -17,7 +17,7 @@ describe("Enclave", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); - const registry = await deployCypherNodeRegistryFixture(); + const registry = await deployCyphernodeRegistryFixture(); const computationModule = await deployComputationModuleFixture(); const outputVerifier = await deployOutputVerifierFixture(); const executionModule = await deployExecutionModuleFixture(); @@ -49,13 +49,13 @@ describe("Enclave", function () { it("correctly sets owner", async function () { const [, , , someSigner] = await ethers.getSigners(); const enclave = await deployEnclaveFixture({ owner: someSigner, registry: AddressTwo }); - expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); + expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); }); - it("correctly sets cypherNodeRegistry address", async function () { + it("correctly sets cyphernodeRegistry address", async function () { const [aSigner] = await ethers.getSigners(); const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo }); - expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); + expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); }); it("correctly sets max duration", async function () { @@ -88,47 +88,47 @@ describe("Enclave", function () { }); }); - describe("setCypherNodeRegistry()", function () { + describe("setCyphernodeRegistry()", function () { it("reverts if not called by owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); - await expect(enclave.connect(notTheOwner).setCypherNodeRegistry(AddressTwo)) + await expect(enclave.connect(notTheOwner).setCyphernodeRegistry(AddressTwo)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if given address(0)", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.setCypherNodeRegistry(ethers.ZeroAddress)) - .to.be.revertedWithCustomError(enclave, "InvalidCypherNodeRegistry") + await expect(enclave.setCyphernodeRegistry(ethers.ZeroAddress)) + .to.be.revertedWithCustomError(enclave, "InvalidCyphernodeRegistry") .withArgs(ethers.ZeroAddress); }); - it("reverts if given address is the same as the current cypherNodeRegistry", async function () { + it("reverts if given address is the same as the current cyphernodeRegistry", async function () { const { enclave, mocks: { registry }, } = await loadFixture(setup); - await expect(enclave.setCypherNodeRegistry(registry)) - .to.be.revertedWithCustomError(enclave, "InvalidCypherNodeRegistry") + await expect(enclave.setCyphernodeRegistry(registry)) + .to.be.revertedWithCustomError(enclave, "InvalidCyphernodeRegistry") .withArgs(registry); }); - it("sets cypherNodeRegistry correctly", async function () { + it("sets cyphernodeRegistry correctly", async function () { const { enclave } = await loadFixture(setup); - expect(await enclave.cypherNodeRegistry()).to.not.equal(AddressTwo); - await enclave.setCypherNodeRegistry(AddressTwo); - expect(await enclave.cypherNodeRegistry()).to.equal(AddressTwo); + expect(await enclave.cyphernodeRegistry()).to.not.equal(AddressTwo); + await enclave.setCyphernodeRegistry(AddressTwo); + expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); }); - it("returns true if cypherNodeRegistry is set successfully", async function () { + it("returns true if cyphernodeRegistry is set successfully", async function () { const { enclave } = await loadFixture(setup); - const result = await enclave.setCypherNodeRegistry.staticCall(AddressTwo); + const result = await enclave.setCyphernodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits CypherNodeRegistrySet event", async function () { + it("emits CyphernodeRegistrySet event", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.setCypherNodeRegistry(AddressTwo)) - .to.emit(enclave, "CypherNodeRegistrySet") + await expect(enclave.setCyphernodeRegistry(AddressTwo)) + .to.emit(enclave, "CyphernodeRegistrySet") .withArgs(AddressTwo); }); }); @@ -565,7 +565,7 @@ describe("Enclave", function () { await expect(enclave.activate(0)).to.not.be.reverted; await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3AlreadyActivated").withArgs(0); }); - it("reverts if cypherNodeRegistry does not return a public key"); + it("reverts if cyphernodeRegistry does not return a public key"); it("sets committeePublicKey correctly"); it("returns true if E3 is activated successfully"); it("emits E3Activated event"); diff --git a/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts index 8dab767c..cd1a588b 100644 --- a/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts +++ b/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts @@ -1,9 +1,9 @@ import { ethers } from "hardhat"; -import { MockCypherNodeRegistry__factory } from "../../types/factories/contracts/test/MockCypherNodeRegistry__factory"; +import { MockCyphernodeRegistry__factory } from "../../types/factories/contracts/test/MockCyphernodeRegistry__factory"; -export async function deployCypherNodeRegistryFixture() { - const deployment = await (await ethers.getContractFactory("MockCypherNodeRegistry")).deploy(); +export async function deployCyphernodeRegistryFixture() { + const deployment = await (await ethers.getContractFactory("MockCyphernodeRegistry")).deploy(); - return MockCypherNodeRegistry__factory.connect(await deployment.getAddress()); + return MockCyphernodeRegistry__factory.connect(await deployment.getAddress()); } From 868de3daa90b39915b8f48f70ff2f0f97fd03f36 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 4 Jun 2024 16:18:53 +1000 Subject: [PATCH 54/62] CypherNode --> Cyphernode --- ...rNodeRegistry.fixture.ts => MockCyphernodeRegistry.fixture.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/evm/test/fixtures/{MockCypherNodeRegistry.fixture.ts => MockCyphernodeRegistry.fixture.ts} (100%) diff --git a/packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts similarity index 100% rename from packages/evm/test/fixtures/MockCypherNodeRegistry.fixture.ts rename to packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts From 6dba3234a4eb1d6703753f0f87769aaf511deb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 4 Jun 2024 12:26:29 +0200 Subject: [PATCH 55/62] Active test: invalid committee public key --- .../contracts/test/MockCyphernodeRegistry.sol | 14 +++++++++++ packages/evm/test/Enclave.spec.ts | 24 ++++++++++++++++++- .../MockCyphernodeRegistry.fixture.ts | 6 ++--- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol index 44151eac..d9380963 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -16,3 +16,17 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { return abi.encodePacked(keccak256(abi.encode(e3Id))); } } + +contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { + function selectCommittee(uint256, address pool, uint32[2] calldata) external pure returns (bool success) { + if (pool == address(2)) { + success = false; + } else { + success = true; + } + } + + function getCommitteePublicKey(uint256 e3Id) external pure returns (bytes memory) { + return hex""; + } +} diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index f4323ed9..07d46851 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -565,7 +565,29 @@ describe("Enclave", function () { await expect(enclave.activate(0)).to.not.be.reverted; await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3AlreadyActivated").withArgs(0); }); - it("reverts if cyphernodeRegistry does not return a public key"); + it("reverts if cyphernodeRegistry does not return a public key", async function () { + const { enclave, request } = await loadFixture(setup); + + await enclave.request( + request.pool, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, + { value: 10 }, + ); + + const prevRegistry = await enclave.cyphernodeRegistry(); + const nextRegistry = await deployCyphernodeRegistryFixture("MockCyphernodeRegistryEmptyKey"); + + await enclave.setCyphernodeRegistry(nextRegistry); + await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); + + await enclave.setCyphernodeRegistry(prevRegistry); + await expect(enclave.activate(0)).to.not.be.reverted; + }); it("sets committeePublicKey correctly"); it("returns true if E3 is activated successfully"); it("emits E3Activated event"); diff --git a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts index cd1a588b..73d87fbe 100644 --- a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts +++ b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts @@ -1,9 +1,9 @@ import { ethers } from "hardhat"; -import { MockCyphernodeRegistry__factory } from "../../types/factories/contracts/test/MockCyphernodeRegistry__factory"; +import { MockCyphernodeRegistry__factory } from "../../types"; -export async function deployCyphernodeRegistryFixture() { - const deployment = await (await ethers.getContractFactory("MockCyphernodeRegistry")).deploy(); +export async function deployCyphernodeRegistryFixture(name?: string) { + const deployment = await (await ethers.getContractFactory(name || "MockCyphernodeRegistry")).deploy(); return MockCyphernodeRegistry__factory.connect(await deployment.getAddress()); } From 47883f14c7e5a2706cba21227018b12f9210c9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 4 Jun 2024 12:42:08 +0200 Subject: [PATCH 56/62] Add committeePublicKey test --- packages/evm/test/Enclave.spec.ts | 30 ++++++++++++++++++- .../MockCyphernodeRegistry.fixture.ts | 3 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 07d46851..c4078fe2 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -588,7 +588,35 @@ describe("Enclave", function () { await enclave.setCyphernodeRegistry(prevRegistry); await expect(enclave.activate(0)).to.not.be.reverted; }); - it("sets committeePublicKey correctly"); + it("sets committeePublicKey correctly", async () => { + const { + enclave, + request, + mocks: { registry }, + } = await loadFixture(setup); + + await enclave.request( + request.pool, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, + { value: 10 }, + ); + + const e3Id = 0; + const publicKey = await registry.getCommitteePublicKey(e3Id); + + let e3 = await enclave.getE3(e3Id); + expect(e3.committeePublicKey).to.not.equal(publicKey); + + await enclave.activate(e3Id); + + e3 = await enclave.getE3(e3Id); + expect(e3.committeePublicKey).to.equal(publicKey); + }); it("returns true if E3 is activated successfully"); it("emits E3Activated event"); }); diff --git a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts index 73d87fbe..99b317df 100644 --- a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts +++ b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts @@ -3,7 +3,8 @@ import { ethers } from "hardhat"; import { MockCyphernodeRegistry__factory } from "../../types"; export async function deployCyphernodeRegistryFixture(name?: string) { + const [signer] = await ethers.getSigners(); const deployment = await (await ethers.getContractFactory(name || "MockCyphernodeRegistry")).deploy(); - return MockCyphernodeRegistry__factory.connect(await deployment.getAddress()); + return MockCyphernodeRegistry__factory.connect(await deployment.getAddress(), signer.provider); } From 31e11eb53c6efaeee63035d11d9e80ef664842ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 4 Jun 2024 12:53:06 +0200 Subject: [PATCH 57/62] Bring prettier width configuration down, and closer to the default. 120 was too wide, 100 is closer to the default of 80 --- packages/evm/.prettierrc.yml | 2 +- packages/evm/contracts/Enclave.sol | 55 +++++++++++++++---- .../interfaces/IComputationModule.sol | 5 +- .../evm/contracts/interfaces/IEnclave.sol | 10 +++- .../contracts/interfaces/IInputValidator.sol | 5 +- .../contracts/interfaces/IOutputVerifier.sol | 5 +- .../contracts/test/MockComputationModule.sol | 5 +- .../contracts/test/MockCyphernodeRegistry.sol | 12 +++- .../evm/contracts/test/MockInputValidator.sol | 5 +- .../evm/contracts/test/MockOutputVerifier.sol | 5 +- packages/evm/test/Enclave.spec.ts | 46 +++++++++++++--- packages/evm/test/fixtures/Enclave.fixture.ts | 4 +- .../MockCyphernodeRegistry.fixture.ts | 4 +- 13 files changed, 129 insertions(+), 34 deletions(-) diff --git a/packages/evm/.prettierrc.yml b/packages/evm/.prettierrc.yml index 99f4ab9a..1383775b 100644 --- a/packages/evm/.prettierrc.yml +++ b/packages/evm/.prettierrc.yml @@ -2,7 +2,7 @@ bracketSpacing: true plugins: - "@trivago/prettier-plugin-sort-imports" - "prettier-plugin-solidity" -printWidth: 120 +printWidth: 100 proseWrap: "always" singleQuote: false tabWidth: 2 diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index acc6e678..596e8511 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -5,7 +5,9 @@ import { IEnclave, E3, IComputationModule, IExecutionModule } from "./interfaces import { ICyphernodeRegistry } from "./interfaces/ICyphernodeRegistry.sol"; import { IInputValidator } from "./interfaces/IInputValidator.sol"; import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// @@ -103,7 +105,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold(threshold)); require(duration > 0 && duration <= maxDuration, InvalidDuration(duration)); // TODO: should 0 be a magic number for infinite duration? - require(computationModules[computationModule], ComputationModuleNotAllowed(computationModule)); + require( + computationModules[computationModule], + ComputationModuleNotAllowed(computationModule) + ); require(executionModules[executionModule], ModuleNotEnabled(address(executionModule))); // TODO: should IDs be incremental or produced deterministic? @@ -130,7 +135,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { }); e3s[e3Id] = e3; - require(cyphernodeRegistry.selectCommittee(e3Id, pool, threshold), CommitteeSelectionFailed()); + require( + cyphernodeRegistry.selectCommittee(e3Id, pool, threshold), + CommitteeSelectionFailed() + ); // TODO: validate that the selected pool accepts both the computation and execution modules. emit E3Requested(e3Id, e3s[e3Id], pool, computationModule, executionModule); @@ -143,6 +151,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { require(e3.expiration == 0, E3AlreadyActivated(e3Id)); bytes memory committeePublicKey = cyphernodeRegistry.getCommitteePublicKey(e3Id); + // Note: This check feels weird require(committeePublicKey.length > 0, CommitteeSelectionFailed()); e3s[e3Id].expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. @@ -163,7 +172,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit InputPublished(e3Id, input); } - function publishCiphertextOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishCiphertextOutput( + uint256 e3Id, + bytes memory data + ) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.expiration <= block.timestamp, InputDeadlineNotPassed(e3Id, e3.expiration)); require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); // TODO: should the output verifier be able to change its mind? i.e. should we be able to call this multiple times? @@ -175,7 +187,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit CiphertextOutputPublished(e3Id, output); } - function publishPlaintextOutput(uint256 e3Id, bytes memory data) external returns (bool success) { + function publishPlaintextOutput( + uint256 e3Id, + bytes memory data + ) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.ciphertextOutput.length > 0, CiphertextOutputNotPublished(e3Id)); require(e3.plaintextOutput.length == 0, PlaintextOutputAlreadyPublished(e3Id)); @@ -199,7 +214,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit MaxDurationSet(_maxDuration); } - function setCyphernodeRegistry(ICyphernodeRegistry _cyphernodeRegistry) public onlyOwner returns (bool success) { + function setCyphernodeRegistry( + ICyphernodeRegistry _cyphernodeRegistry + ) public onlyOwner returns (bool success) { require( address(_cyphernodeRegistry) != address(0) && _cyphernodeRegistry != cyphernodeRegistry, InvalidCyphernodeRegistry(_cyphernodeRegistry) @@ -209,28 +226,42 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit CyphernodeRegistrySet(address(_cyphernodeRegistry)); } - function enableComputationModule(IComputationModule computationModule) public onlyOwner returns (bool success) { - require(!computationModules[computationModule], ModuleAlreadyEnabled(address(computationModule))); + function enableComputationModule( + IComputationModule computationModule + ) public onlyOwner returns (bool success) { + require( + !computationModules[computationModule], + ModuleAlreadyEnabled(address(computationModule)) + ); computationModules[computationModule] = true; success = true; emit ComputationModuleEnabled(computationModule); } - function enableExecutionModule(IExecutionModule executionModule) public onlyOwner returns (bool success) { + function enableExecutionModule( + IExecutionModule executionModule + ) public onlyOwner returns (bool success) { require(!executionModules[executionModule], ModuleAlreadyEnabled(address(executionModule))); executionModules[executionModule] = true; success = true; emit ExecutionModuleEnabled(executionModule); } - function disableComputationModule(IComputationModule computationModule) public onlyOwner returns (bool success) { - require(computationModules[computationModule], ModuleNotEnabled(address(computationModule))); + function disableComputationModule( + IComputationModule computationModule + ) public onlyOwner returns (bool success) { + require( + computationModules[computationModule], + ModuleNotEnabled(address(computationModule)) + ); delete computationModules[computationModule]; success = true; emit ComputationModuleDisabled(computationModule); } - function disableExecutionModule(IExecutionModule executionModule) public onlyOwner returns (bool success) { + function disableExecutionModule( + IExecutionModule executionModule + ) public onlyOwner returns (bool success) { require(executionModules[executionModule], ModuleNotEnabled(address(executionModule))); delete executionModules[executionModule]; success = true; diff --git a/packages/evm/contracts/interfaces/IComputationModule.sol b/packages/evm/contracts/interfaces/IComputationModule.sol index 89d78842..a5b6258c 100644 --- a/packages/evm/contracts/interfaces/IComputationModule.sol +++ b/packages/evm/contracts/interfaces/IComputationModule.sol @@ -14,5 +14,8 @@ interface IComputationModule { /// @param outputData ABI encoded output data to be verified. /// @return output The output data to be published. /// @return success Whether the output data is valid. - function verify(uint256 e3Id, bytes memory outputData) external returns (bytes memory output, bool success); + function verify( + uint256 e3Id, + bytes memory outputData + ) external returns (bytes memory output, bool success); } diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 40b3c237..363902ea 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -116,7 +116,10 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to verify. /// @return success True if the output was successfully published. - function publishCiphertextOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishCiphertextOutput( + uint256 e3Id, + bytes memory data + ) external returns (bool success); /// @notice This function should be called to publish the plaintext output of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the output has not been published. @@ -124,7 +127,10 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to decrypt. /// @return success True if the output was successfully decrypted. - function publishPlaintextOutput(uint256 e3Id, bytes memory data) external returns (bool success); + function publishPlaintextOutput( + uint256 e3Id, + bytes memory data + ) external returns (bool success); //////////////////////////////////////////////////////////// // // diff --git a/packages/evm/contracts/interfaces/IInputValidator.sol b/packages/evm/contracts/interfaces/IInputValidator.sol index 1d509ec1..257af4da 100644 --- a/packages/evm/contracts/interfaces/IInputValidator.sol +++ b/packages/evm/contracts/interfaces/IInputValidator.sol @@ -6,5 +6,8 @@ interface IInputValidator { /// @param params ABI encoded input parameters. /// @return input The input data to be published. /// @return success Whether the input parameters are valid. - function validate(address sender, bytes memory params) external returns (bytes memory input, bool success); + function validate( + address sender, + bytes memory params + ) external returns (bytes memory input, bool success); } diff --git a/packages/evm/contracts/interfaces/IOutputVerifier.sol b/packages/evm/contracts/interfaces/IOutputVerifier.sol index e6e1100d..56d44441 100644 --- a/packages/evm/contracts/interfaces/IOutputVerifier.sol +++ b/packages/evm/contracts/interfaces/IOutputVerifier.sol @@ -6,5 +6,8 @@ interface IOutputVerifier { /// @param e3Id ID of the E3. /// @param data ABI encoded output data to be verified. /// @return output Ciphertext output of the given computation. - function verify(uint256 e3Id, bytes memory data) external returns (bytes memory output, bool success); + function verify( + uint256 e3Id, + bytes memory data + ) external returns (bytes memory output, bool success); } diff --git a/packages/evm/contracts/test/MockComputationModule.sol b/packages/evm/contracts/test/MockComputationModule.sol index e7ffe424..d4cdf28b 100644 --- a/packages/evm/contracts/test/MockComputationModule.sol +++ b/packages/evm/contracts/test/MockComputationModule.sol @@ -13,7 +13,10 @@ contract MockComputationModule is IComputationModule { } } - function verify(uint256, bytes memory outputData) external pure returns (bytes memory output, bool success) { + function verify( + uint256, + bytes memory outputData + ) external pure returns (bytes memory output, bool success) { return (outputData, true); } } diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol index d9380963..b8289f17 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -4,7 +4,11 @@ pragma solidity >=0.8.26; import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; contract MockCyphernodeRegistry is ICyphernodeRegistry { - function selectCommittee(uint256, address pool, uint32[2] calldata) external pure returns (bool success) { + function selectCommittee( + uint256, + address pool, + uint32[2] calldata + ) external pure returns (bool success) { if (pool == address(2)) { success = false; } else { @@ -18,7 +22,11 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { } contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { - function selectCommittee(uint256, address pool, uint32[2] calldata) external pure returns (bool success) { + function selectCommittee( + uint256, + address pool, + uint32[2] calldata + ) external pure returns (bool success) { if (pool == address(2)) { success = false; } else { diff --git a/packages/evm/contracts/test/MockInputValidator.sol b/packages/evm/contracts/test/MockInputValidator.sol index a76909d6..e917fd08 100644 --- a/packages/evm/contracts/test/MockInputValidator.sol +++ b/packages/evm/contracts/test/MockInputValidator.sol @@ -4,7 +4,10 @@ pragma solidity >=0.8.26; import { IInputValidator } from "../interfaces/IInputValidator.sol"; contract MockInputValidator is IInputValidator { - function validate(address, bytes memory params) external pure returns (bytes memory input, bool success) { + function validate( + address, + bytes memory params + ) external pure returns (bytes memory input, bool success) { (input) = abi.decode(params, (bytes)); success = true; } diff --git a/packages/evm/contracts/test/MockOutputVerifier.sol b/packages/evm/contracts/test/MockOutputVerifier.sol index 37434b3e..d4da9f03 100644 --- a/packages/evm/contracts/test/MockOutputVerifier.sol +++ b/packages/evm/contracts/test/MockOutputVerifier.sol @@ -4,7 +4,10 @@ pragma solidity >=0.8.26; import { IOutputVerifier } from "../interfaces/IOutputVerifier.sol"; contract MockOutputVerifier is IOutputVerifier { - function verify(uint256, bytes memory data) external pure returns (bytes memory output, bool success) { + function verify( + uint256, + bytes memory data + ) external pure returns (bytes memory output, bool success) { (output) = abi.decode(data, (bytes)); success = true; } diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index c4078fe2..28ae277b 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -23,7 +23,10 @@ describe("Enclave", function () { const executionModule = await deployExecutionModuleFixture(); const inputValidator = await deployInputValidatorFixture(); - const enclave = await deployEnclaveFixture({ owner, registry: await registry.getAddress() }); + const enclave = await deployEnclaveFixture({ + owner, + registry: await registry.getAddress(), + }); await enclave.enableComputationModule(await computationModule.getAddress()); await enclave.enableExecutionModule(await executionModule.getAddress()); @@ -32,7 +35,13 @@ describe("Enclave", function () { owner, notTheOwner, enclave, - mocks: { computationModule, outputVerifier, executionModule, inputValidator, registry }, + mocks: { + computationModule, + outputVerifier, + executionModule, + inputValidator, + registry, + }, request: { pool: ethers.ZeroAddress, threshold: [2, 2] as [number, number], @@ -48,19 +57,29 @@ describe("Enclave", function () { describe("constructor / initialize()", function () { it("correctly sets owner", async function () { const [, , , someSigner] = await ethers.getSigners(); - const enclave = await deployEnclaveFixture({ owner: someSigner, registry: AddressTwo }); + const enclave = await deployEnclaveFixture({ + owner: someSigner, + registry: AddressTwo, + }); expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); }); it("correctly sets cyphernodeRegistry address", async function () { const [aSigner] = await ethers.getSigners(); - const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo }); + const enclave = await deployEnclaveFixture({ + owner: aSigner, + registry: AddressTwo, + }); expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); }); it("correctly sets max duration", async function () { const [aSigner] = await ethers.getSigners(); - const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo, maxDuration: 9876 }); + const enclave = await deployEnclaveFixture({ + owner: aSigner, + registry: AddressTwo, + maxDuration: 9876, + }); expect(await enclave.maxDuration()).to.equal(9876); }); }); @@ -137,7 +156,9 @@ describe("Enclave", function () { it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.getE3(1)).to.be.revertedWithCustomError(enclave, "E3DoesNotExist").withArgs(1); + await expect(enclave.getE3(1)) + .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") + .withArgs(1); }); it("returns correct E3 details", async function () { const { enclave, request } = await loadFixture(setup); @@ -545,7 +566,9 @@ describe("Enclave", function () { it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3DoesNotExist").withArgs(0); + await expect(enclave.activate(0)) + .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") + .withArgs(0); }); it("reverts if E3 has already been activated", async function () { const { enclave, request } = await loadFixture(setup); @@ -563,7 +586,9 @@ describe("Enclave", function () { await expect(enclave.getE3(0)).to.not.be.reverted; await expect(enclave.activate(0)).to.not.be.reverted; - await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "E3AlreadyActivated").withArgs(0); + await expect(enclave.activate(0)) + .to.be.revertedWithCustomError(enclave, "E3AlreadyActivated") + .withArgs(0); }); it("reverts if cyphernodeRegistry does not return a public key", async function () { const { enclave, request } = await loadFixture(setup); @@ -583,7 +608,10 @@ describe("Enclave", function () { const nextRegistry = await deployCyphernodeRegistryFixture("MockCyphernodeRegistryEmptyKey"); await enclave.setCyphernodeRegistry(nextRegistry); - await expect(enclave.activate(0)).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); + await expect(enclave.activate(0)).to.be.revertedWithCustomError( + enclave, + "CommitteeSelectionFailed", + ); await enclave.setCyphernodeRegistry(prevRegistry); await expect(enclave.activate(0)).to.not.be.reverted; diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index 36c61c04..539e7cc9 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -12,7 +12,9 @@ export async function deployEnclaveFixture({ registry: string; maxDuration?: number; }) { - const deployment = await (await ethers.getContractFactory("Enclave")).deploy(owner, registry, maxDuration); + const deployment = await ( + await ethers.getContractFactory("Enclave") + ).deploy(owner, registry, maxDuration); return Enclave__factory.connect(await deployment.getAddress(), owner); } diff --git a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts index 99b317df..258ce6c1 100644 --- a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts +++ b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts @@ -4,7 +4,9 @@ import { MockCyphernodeRegistry__factory } from "../../types"; export async function deployCyphernodeRegistryFixture(name?: string) { const [signer] = await ethers.getSigners(); - const deployment = await (await ethers.getContractFactory(name || "MockCyphernodeRegistry")).deploy(); + const deployment = await ( + await ethers.getContractFactory(name || "MockCyphernodeRegistry") + ).deploy(); return MockCyphernodeRegistry__factory.connect(await deployment.getAddress(), signer.provider); } From 6076376382c5ac705289b752982078123701e3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crist=C3=B3v=C3=A3o=20Honorato?= Date: Tue, 4 Jun 2024 17:54:07 +0200 Subject: [PATCH 58/62] Test e3 action event emission and return value --- packages/evm/test/Enclave.spec.ts | 41 +++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 28ae277b..cbd0ca08 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -645,8 +645,45 @@ describe("Enclave", function () { e3 = await enclave.getE3(e3Id); expect(e3.committeePublicKey).to.equal(publicKey); }); - it("returns true if E3 is activated successfully"); - it("emits E3Activated event"); + it("returns true if E3 is activated successfully", async () => { + const { enclave, request } = await loadFixture(setup); + + await enclave.request( + request.pool, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, + { value: 10 }, + ); + + const e3Id = 0; + + expect(await enclave.activate.staticCall(e3Id)).to.be.equal(true); + }); + it("emits E3Activated event", async () => { + const { enclave, request } = await loadFixture(setup); + + await enclave.request( + request.pool, + request.threshold, + request.duration, + request.computationModule, + request.cMParams, + request.executionModule, + request.eMParams, + { value: 10 }, + ); + + const e3Id = 0; + const e3 = await enclave.getE3(e3Id); + + expect(await enclave.activate(e3Id)) + .to.emit(enclave, "E3Activated") + .withArgs(e3Id, e3.expiration, e3.committeePublicKey); + }); }); describe("publishInput()", function () { From de170292005381778eaaa967fb91ef1f474d2ec1 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 5 Jun 2024 06:44:36 +1000 Subject: [PATCH 59/62] start drafting ownable cyphernodeRegistry --- packages/evm/contracts/Enclave.sol | 6 +- .../interfaces/ICyphernodeRegistry.sol | 12 +--- .../evm/contracts/interfaces/IEnclave.sol | 6 +- .../registry/CyphernodeRegistryOwnable.sol | 70 +++++++++++++++++++ .../contracts/test/MockCyphernodeRegistry.sol | 10 +-- packages/evm/test/Enclave.spec.ts | 4 +- 6 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 596e8511..5bb409cc 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -91,7 +91,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// function request( - address pool, // TODO: should we allow for multiple pools? + address[] memory pools, // TODO: should we allow for multiple pools? uint32[2] calldata threshold, uint256 duration, // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are published before the request is made? This kind of assumes the cypher nodes have already been selected and generated a shared secret. IComputationModule computationModule, @@ -136,12 +136,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3s[e3Id] = e3; require( - cyphernodeRegistry.selectCommittee(e3Id, pool, threshold), + cyphernodeRegistry.selectCommittee(e3Id, pools, threshold), CommitteeSelectionFailed() ); // TODO: validate that the selected pool accepts both the computation and execution modules. - emit E3Requested(e3Id, e3s[e3Id], pool, computationModule, executionModule); + emit E3Requested(e3Id, e3s[e3Id], pools, computationModule, executionModule); } function activate(uint256 e3Id) external returns (bool success) { diff --git a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol index 6a99ba46..1d91fb9c 100644 --- a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol @@ -12,22 +12,14 @@ interface ICyphernodeRegistry { /// @param node Address of the node. event NodeRemoved(uint256 indexed nodeId, address indexed node); - /// @notice This event MUST be emitted when a pool is added to the registry. - /// @param poolId ID of the pool. - event PoolAdded(address indexed poolId); - - /// @notice This event MUST be emitted when a pool is removed from the registry. - /// @param poolId ID of the pool. - event PoolRemoved(address indexed poolId); - /// @notice This function should be called by the Enclave contract to select a node committee. /// @param e3Id ID of the E3 for which to select the committee. - /// @param poolId ID of the pool of nodes from which to select the committee. + /// @param pools IDs of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @return success True if committee selection was successfully initiated. function selectCommittee( uint256 e3Id, - address poolId, + address[] memory pools, uint32[2] calldata threshold ) external returns (bool success); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 363902ea..11047763 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -19,7 +19,7 @@ interface IEnclave { event E3Requested( uint256 e3Id, E3 e3, - address indexed pool, + address[] pool, IComputationModule indexed computationModule, IExecutionModule indexed executionModule ); @@ -77,7 +77,7 @@ interface IEnclave { /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3). /// @dev This function MUST emit the E3Requested event. - /// @param pool ID of the pool of nodes from which to select the committee. + /// @param pools IDs of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @param duration The duration of the computation in seconds. /// @param computationModule Address of the computation module. @@ -87,7 +87,7 @@ interface IEnclave { /// @return e3Id ID of the E3. /// @return e3 The E3 struct. function request( - address pool, + address[] memory pools, uint32[2] calldata threshold, uint256 duration, IComputationModule computationModule, diff --git a/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol new file mode 100644 index 00000000..92e98db3 --- /dev/null +++ b/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { + struct Committee { + address[] nodes; + uint32[2] threshold; + address[] pools; + bytes publicKey; + } + + struct Node { + bool eligible; + // Number of duties the node has not yet completed. + // Incremented each time a duty is added, decremented each time a duty is completed. + uint256 outstandingDuties; + } + + //////////////////////////////////////////////////////////// + // // + // Storage Variables // + // // + //////////////////////////////////////////////////////////// + + mapping(uint256 e3 => Committee committee) public committees; + mapping(address nodeId => Node node) public nodes; + + //////////////////////////////////////////////////////////// + // // + // Initialization // + // // + //////////////////////////////////////////////////////////// + + constructor(address _owner) { + initialize(_owner); + } + + function initialize(address _owner) public initializer { + __Ownable_init(_owner); + } + + //////////////////////////////////////////////////////////// + // // + // Core Entrypoints // + // // + //////////////////////////////////////////////////////////// + + function selectCommittee( + uint256 e3Id, + address[] memory pools, + uint32[2] calldata threshold + ) external pure override returns (bool success) {} + + function getCommitteePublicKey(uint256 e3Id) external pure override returns (bytes memory) {} + + //////////////////////////////////////////////////////////// + // // + // Set Functions // + // // + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // // + // Get Functions // + // // + //////////////////////////////////////////////////////////// +} diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol index b8289f17..664f0ab1 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -6,10 +6,10 @@ import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; contract MockCyphernodeRegistry is ICyphernodeRegistry { function selectCommittee( uint256, - address pool, + address[] memory pools, uint32[2] calldata ) external pure returns (bool success) { - if (pool == address(2)) { + if (pools[0] == address(2)) { success = false; } else { success = true; @@ -24,17 +24,17 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { function selectCommittee( uint256, - address pool, + address[] memory pools, uint32[2] calldata ) external pure returns (bool success) { - if (pool == address(2)) { + if (pools[0] == address(2)) { success = false; } else { success = true; } } - function getCommitteePublicKey(uint256 e3Id) external pure returns (bytes memory) { + function getCommitteePublicKey(uint256) external pure returns (bytes memory) { return hex""; } } diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index cbd0ca08..53a21116 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -43,7 +43,7 @@ describe("Enclave", function () { registry, }, request: { - pool: ethers.ZeroAddress, + pool: [ethers.ZeroAddress], threshold: [2, 2] as [number, number], duration: time.duration.days(30), computationModule: await computationModule.getAddress(), @@ -507,7 +507,7 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( - AddressTwo, + [AddressTwo], request.threshold, request.duration, request.computationModule, From 50a9383bd1b8ff19c5a3f0568fde3989d8f38c4a Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 5 Jun 2024 15:04:41 +1000 Subject: [PATCH 60/62] First crack at implementing CyphernodeRegistryOwnable --- .../interfaces/ICyphernodeRegistry.sol | 14 ++++ .../evm/contracts/interfaces/INodePool.sol | 7 ++ .../registry/CyphernodeRegistryOwnable.sol | 80 +++++++++++++++++-- 3 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 packages/evm/contracts/interfaces/INodePool.sol diff --git a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol index 1d91fb9c..be7e3a55 100644 --- a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol @@ -2,6 +2,16 @@ pragma solidity >=0.8.26; interface ICyphernodeRegistry { + /// @notice This event MUST be emitted when a committee is selected for an E3. + event CommitteeRequested(uint256 indexed e3Id, address[] pools, uint32[2] threshold); + + event CommitteeSelected( + uint256 indexed e3Id, + address[] nodes, + bytes32[] merkleRoots, + bytes publicKey + ); + /// @notice This event MUST be emitted when a node is added to the registry. /// @param nodeId ID of the node. /// @param node Address of the node. @@ -12,6 +22,10 @@ interface ICyphernodeRegistry { /// @param node Address of the node. event NodeRemoved(uint256 indexed nodeId, address indexed node); + /// @notice This event MUST be emitted when `encalve` is set. + /// @param enclave Address of the enclave contract. + event EnclaveSet(address indexed enclave); + /// @notice This function should be called by the Enclave contract to select a node committee. /// @param e3Id ID of the E3 for which to select the committee. /// @param pools IDs of the pool of nodes from which to select the committee. diff --git a/packages/evm/contracts/interfaces/INodePool.sol b/packages/evm/contracts/interfaces/INodePool.sol new file mode 100644 index 00000000..bf1a9100 --- /dev/null +++ b/packages/evm/contracts/interfaces/INodePool.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.26; + +interface INodePool { + /// @notice This function MUST return the Merkle root of this contract's curated pool of nodes. + function merkleRoot() external returns (bytes32 merkleRoot); +} diff --git a/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol index 92e98db3..1057c2b2 100644 --- a/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol +++ b/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol @@ -2,13 +2,16 @@ pragma solidity >=0.8.26; import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { struct Committee { address[] nodes; uint32[2] threshold; address[] pools; + bytes32[] merkleRoots; bytes publicKey; } @@ -25,21 +28,48 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// + address public enclave; + mapping(uint256 e3 => Committee committee) public committees; mapping(address nodeId => Node node) public nodes; + //////////////////////////////////////////////////////////// + // // + // Errors // + // // + //////////////////////////////////////////////////////////// + + error CommitteeAlreadyExists(); + error CommitteeAlreadyPublished(); + error CommitteeDoesNotExist(); + error NoPublicKeyPublished(); + error OnlyEnclave(); + + //////////////////////////////////////////////////////////// + // // + // Modifiers // + // // + //////////////////////////////////////////////////////////// + + modifier onlyEnclave() { + require(msg.sender == enclave, OnlyEnclave()); + _; + } + //////////////////////////////////////////////////////////// // // // Initialization // // // //////////////////////////////////////////////////////////// - constructor(address _owner) { - initialize(_owner); + constructor(address _owner, address _enclave) { + initialize(_owner, _enclave); } - function initialize(address _owner) public initializer { - __Ownable_init(_owner); + function initialize(address _owner, address _enclave) public initializer { + __Ownable_init(msg.sender); + setEnclave(_enclave); + transferOwnership(_owner); } //////////////////////////////////////////////////////////// @@ -52,9 +82,30 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { uint256 e3Id, address[] memory pools, uint32[2] calldata threshold - ) external pure override returns (bool success) {} + ) external onlyEnclave returns (bool success) { + Committee storage committee = committees[e3Id]; + require(committee.threshold.length == 0, CommitteeAlreadyExists()); + committee.threshold = threshold; + committee.pools = pools; + success = true; + + emit CommitteeRequested(e3Id, pools, threshold); + } - function getCommitteePublicKey(uint256 e3Id) external pure override returns (bytes memory) {} + function publishCommittee( + uint256 e3Id, + address[] memory _nodes, + bytes32[] memory merkleRoots, + bytes memory publicKey + ) external onlyOwner { + Committee storage committee = committees[e3Id]; + require(keccak256(committee.publicKey) == keccak256(hex""), CommitteeAlreadyPublished()); + committee.nodes = _nodes; + committee.merkleRoots = merkleRoots; + committee.publicKey = publicKey; + + emit CommitteeSelected(e3Id, _nodes, merkleRoots, publicKey); + } //////////////////////////////////////////////////////////// // // @@ -62,9 +113,24 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// + function setEnclave(address _enclave) public onlyOwner { + enclave = _enclave; + emit EnclaveSet(_enclave); + } + //////////////////////////////////////////////////////////// // // // Get Functions // // // //////////////////////////////////////////////////////////// + + function getCommitteePublicKey(uint256 e3Id) external view returns (bytes memory publicKey) { + publicKey = committees[e3Id].publicKey; + require(publicKey.length > 0, NoPublicKeyPublished()); + } + + function getCommittee(uint256 e3Id) external view returns (Committee memory committee) { + committee = committees[e3Id]; + require(committees[e3Id].threshold.length > 0, CommitteeDoesNotExist()); + } } From 72f187d5fa80f054e31f6fdc71b2da8d3c81b9de Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 5 Jun 2024 15:50:03 +1000 Subject: [PATCH 61/62] squash linter errors --- package.json | 1 + packages/evm/.eslintrc.yml | 2 +- packages/evm/.solhint.json | 4 +- packages/evm/contracts/Enclave.sol | 33 ++- .../evm/contracts/interfaces/IEnclave.sol | 14 +- .../contracts/test/MockComputationModule.sol | 1 + .../contracts/test/MockCyphernodeRegistry.sol | 6 +- .../contracts/test/MockExecutionModule.sol | 1 + packages/evm/package.json | 3 +- packages/evm/test/Enclave.spec.ts | 2 +- packages/evm/yarn.lock | 191 +++++++++--------- 11 files changed, 137 insertions(+), 121 deletions(-) diff --git a/package.json b/package.json index a10196b9..c5e4450c 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@gnosisguild/enclave", "description": "Enclave is an open-source protocol for Encrypted Execution Environments (E3).", "version": "0.0.0", + "license": "LGPL-3.0-only", "author": { "name": "gnosisguild", "url": "https://github.com/gnosisguild" diff --git a/packages/evm/.eslintrc.yml b/packages/evm/.eslintrc.yml index e19402e0..27672a35 100644 --- a/packages/evm/.eslintrc.yml +++ b/packages/evm/.eslintrc.yml @@ -5,7 +5,7 @@ extends: - "prettier" parser: "@typescript-eslint/parser" parserOptions: - project: "packages/evm/tsconfig.json" + project: "tsconfig.json" plugins: - "@typescript-eslint" root: true diff --git a/packages/evm/.solhint.json b/packages/evm/.solhint.json index 122f1f69..78d8b176 100644 --- a/packages/evm/.solhint.json +++ b/packages/evm/.solhint.json @@ -3,12 +3,14 @@ "plugins": ["prettier"], "rules": { "code-complexity": ["error", 8], - "compiler-version": ["error", ">=0.8.4"], + "compiler-version": ["error", ">=0.8.26"], "func-visibility": ["error", { "ignoreConstructors": true }], "max-line-length": ["error", 120], "named-parameters-mapping": "warn", "no-console": "off", "not-rely-on-time": "off", + "gas-custom-errors": "off", + "one-contract-per-file": "off", "prettier/prettier": [ "error", { diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 5bb409cc..d5e7ca6f 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -26,12 +26,15 @@ contract Enclave is IEnclave, OwnableUpgradeable { // But perhaps this is one place where node pools might be utilized, allowing nodes to // opt in to being selected for specific computations, along with the corresponding slashing conditions. // This would reduce the governance overhead for Enclave. - // TODO: add setter function - mapping(IComputationModule => bool allowed) public computationModules; // Mapping of allowed computation modules. - // TODO: add setter function - mapping(IExecutionModule => bool allowed) public executionModules; // Mapping of allowed execution modules. - mapping(uint256 id => E3) public e3s; // Mapping of E3s. + // Mapping of allowed computation modules. + mapping(IComputationModule computationModule => bool allowed) public computationModules; + + // Mapping of allowed execution modules. + mapping(IExecutionModule executionModule => bool allowed) public executionModules; + + // Mapping of E3s. + mapping(uint256 id => E3 e3) public e3s; //////////////////////////////////////////////////////////// // // @@ -93,18 +96,22 @@ contract Enclave is IEnclave, OwnableUpgradeable { function request( address[] memory pools, // TODO: should we allow for multiple pools? uint32[2] calldata threshold, - uint256 duration, // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are published before the request is made? This kind of assumes the cypher nodes have already been selected and generated a shared secret. + // TODO: do we also need a start block/time? Would it be possible to have computations where inputs are + //published before the request is made? This kind of assumes the cypher nodes have already been selected + // and generated a shared secret. + uint256 duration, IComputationModule computationModule, bytes memory computationParams, IExecutionModule executionModule, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3) { // TODO: allow for other payment methods or only native tokens? - // TODO: should payment checks be done somewhere else? Perhaps in the computation module or cypher node registry? + // TODO: should payment checks be somewhere else? Perhaps in the computation module or cyphernode registry? require(msg.value > 0, PaymentRequired(msg.value)); require(threshold[1] >= threshold[0] && threshold[0] > 0, InvalidThreshold(threshold)); - require(duration > 0 && duration <= maxDuration, InvalidDuration(duration)); // TODO: should 0 be a magic number for infinite duration? + // TODO: should 0 be a magic number for infinite duration? + require(duration > 0 && duration <= maxDuration, InvalidDuration(duration)); require( computationModules[computationModule], ComputationModuleNotAllowed(computationModule) @@ -154,7 +161,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { // Note: This check feels weird require(committeePublicKey.length > 0, CommitteeSelectionFailed()); - e3s[e3Id].expiration = block.timestamp + maxDuration; // TODO: this should be based on the duration requested, not the current max duration. + // TODO: this should be based on the duration requested, not the current max duration. + e3s[e3Id].expiration = block.timestamp + maxDuration; e3s[e3Id].committeePublicKey = committeePublicKey; emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey); @@ -164,7 +172,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { function publishInput(uint256 e3Id, bytes memory data) external returns (bool success) { E3 memory e3 = getE3(e3Id); - require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); // TODO: should we have an input window, including both a start and end timestamp? + // TODO: should we have an input window, including both a start and end timestamp? + require(e3.expiration > block.timestamp, InputDeadlinePassed(e3Id, e3.expiration)); bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); @@ -178,7 +187,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { ) external returns (bool success) { E3 memory e3 = getE3(e3Id); require(e3.expiration <= block.timestamp, InputDeadlineNotPassed(e3Id, e3.expiration)); - require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); // TODO: should the output verifier be able to change its mind? i.e. should we be able to call this multiple times? + // TODO: should the output verifier be able to change its mind? + //i.e. should we be able to call this multiple times? + require(e3.ciphertextOutput.length == 0, CiphertextOutputAlreadyPublished(e3Id)); bytes memory output; (output, success) = e3.outputVerifier.verify(e3Id, data); require(success, InvalidOutput()); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 11047763..fe745b13 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -30,17 +30,20 @@ interface IEnclave { /// @param committeePublicKey Public key of the committee. event E3Activated(uint256 e3Id, uint256 expiration, bytes committeePublicKey); - /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published. + /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is + /// successfully published. /// @param e3Id ID of the E3. /// @param data ABI encoded input data. event InputPublished(uint256 indexed e3Id, bytes data); - /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published. + /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) + /// is successfully published. /// @param e3Id ID of the E3. /// @param plaintextOutput ABI encoded plaintext output. event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput); - /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published. + /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) + /// is successfully published. /// @param e3Id ID of the E3. /// @param ciphertextOutput ABI encoded ciphertext output. event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput); @@ -96,7 +99,8 @@ interface IEnclave { bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3); - /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input. + /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been + /// initialized and is ready for input. /// @dev This function MUST emit the E3Activated event. /// @dev This function MUST revert if the given E3 has not yet been requested. /// @dev This function MUST revert if the selected node committee has not yet published a public key. @@ -121,7 +125,7 @@ interface IEnclave { bytes memory data ) external returns (bool success); - /// @notice This function should be called to publish the plaintext output of an Encrypted Execution Environment (E3). + /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3). /// @dev This function MUST revert if the output has not been published. /// @dev This function MUST emit the PlaintextOutputPublished event. /// @param e3Id ID of the E3. diff --git a/packages/evm/contracts/test/MockComputationModule.sol b/packages/evm/contracts/test/MockComputationModule.sol index d4cdf28b..059da32d 100644 --- a/packages/evm/contracts/test/MockComputationModule.sol +++ b/packages/evm/contracts/test/MockComputationModule.sol @@ -8,6 +8,7 @@ contract MockComputationModule is IComputationModule { function validate(bytes memory params) external pure returns (IInputValidator inputValidator) { require(params.length == 32, "invalid params"); + // solhint-disable no-inline-assembly assembly { inputValidator := mload(add(params, 32)) } diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol index 664f0ab1..49726fab 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -17,7 +17,11 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { } function getCommitteePublicKey(uint256 e3Id) external pure returns (bytes memory) { - return abi.encodePacked(keccak256(abi.encode(e3Id))); + if (e3Id == type(uint256).max) { + return hex""; + } else { + return abi.encodePacked(keccak256(abi.encode(e3Id))); + } } } diff --git a/packages/evm/contracts/test/MockExecutionModule.sol b/packages/evm/contracts/test/MockExecutionModule.sol index a381cb5c..18d180dc 100644 --- a/packages/evm/contracts/test/MockExecutionModule.sol +++ b/packages/evm/contracts/test/MockExecutionModule.sol @@ -8,6 +8,7 @@ contract MockExecutionModule is IExecutionModule { function validate(bytes memory params) external pure returns (IOutputVerifier outputVerifier) { require(params.length == 32, invalidParams()); + // solhint-disable no-inline-assembly assembly { outputVerifier := mload(add(params, 32)) } diff --git a/packages/evm/package.json b/packages/evm/package.json index a303f6d4..f6b4db13 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -2,6 +2,7 @@ "name": "@gnosisguild/enclave", "description": "Enclave is an open-source protocol for Encrypted Execution Environments (E3).", "version": "0.0.0", + "license": "LGPL-3.0-only", "author": { "name": "gnosisguild", "url": "https://github.com/gnosisguild" @@ -24,7 +25,7 @@ "@typescript-eslint/parser": "^7.11.0", "chai": "^4.3.10", "cross-env": "^7.0.3", - "eslint": "^9.4.0", + "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "ethers": "^6.9.0", "fs-extra": "^11.2.0", diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 53a21116..d49c7549 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -680,7 +680,7 @@ describe("Enclave", function () { const e3Id = 0; const e3 = await enclave.getE3(e3Id); - expect(await enclave.activate(e3Id)) + await expect(enclave.activate(e3Id)) .to.emit(enclave, "E3Activated") .withArgs(e3Id, e3.expiration, e3.committeePublicKey); }); diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index f3c5f2a3..c287ce52 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -157,39 +157,25 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/config-array@^0.15.1": - version "0.15.1" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.15.1.tgz#1fa78b422d98f4e7979f2211a1fde137e26c7d61" - integrity sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ== - dependencies: - "@eslint/object-schema" "^2.1.3" - debug "^4.3.1" - minimatch "^3.0.5" - -"@eslint/eslintrc@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" - integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^10.0.1" - globals "^14.0.0" + espree "^9.6.0" + globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.4.0": - version "9.4.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.4.0.tgz#96a2edd37ec0551ce5f9540705be23951c008a0c" - integrity sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg== - -"@eslint/object-schema@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.3.tgz#e65ae80ee2927b4fd8c5c26b15ecacc2b2a6cc2a" - integrity sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw== +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== "@ethereumjs/rlp@^4.0.1": version "4.0.1" @@ -552,15 +538,24 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/retry@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" - integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -1303,6 +1298,11 @@ "@typescript-eslint/types" "7.11.0" eslint-visitor-keys "^3.4.3" +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1328,7 +1328,7 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.11.3, acorn@^8.4.1: +acorn@^8.4.1, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -2073,6 +2073,13 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -2183,55 +2190,54 @@ eslint-config-prettier@^9.1.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== -eslint-scope@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" - integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" - integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== - -eslint@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.4.0.tgz#79150c3610ae606eb131f1d648d5f43b3d45f3cd" - integrity sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA== +eslint@^8.56.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/config-array" "^0.15.1" - "@eslint/eslintrc" "^3.1.0" - "@eslint/js" "9.4.0" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.3.0" "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" + doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^8.0.1" - eslint-visitor-keys "^4.0.0" - espree "^10.0.1" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^8.0.0" + file-entry-cache "^6.0.1" find-up "^5.0.0" glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" + js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" @@ -2241,14 +2247,14 @@ eslint@^9.4.0: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" - integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.11.3" + acorn "^8.9.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.0.0" + eslint-visitor-keys "^3.4.1" esprima@2.7.x, esprima@^2.7.1: version "2.7.3" @@ -2480,12 +2486,12 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -file-entry-cache@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" - integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: - flat-cache "^4.0.0" + flat-cache "^3.0.4" fill-range@^7.1.1: version "7.1.1" @@ -2516,13 +2522,14 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" -flat-cache@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" - integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: flatted "^3.2.9" - keyv "^4.5.4" + keyv "^4.5.3" + rimraf "^3.0.2" flat@^5.0.2: version "5.0.2" @@ -2788,10 +2795,12 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" globby@^10.0.1: version "10.0.2" @@ -3324,7 +3333,7 @@ keccak@^3.0.0, keccak@^3.0.2: node-gyp-build "^4.2.0" readable-stream "^3.6.0" -keyv@^4.5.3, keyv@^4.5.4: +keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -4092,6 +4101,13 @@ rimraf@^2.2.8: dependencies: glob "^7.1.3" +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^5.0.5: version "5.0.7" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" @@ -4401,16 +4417,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4435,14 +4442,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4836,16 +4836,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== From 21645360fd479d898bd760a4a79e60a0e6af7b09 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 5 Jun 2024 21:07:25 +1000 Subject: [PATCH 62/62] fill missing natspec comments on ICyphernodeRegistry --- packages/evm/contracts/interfaces/ICyphernodeRegistry.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol index be7e3a55..1c6077f1 100644 --- a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol @@ -3,8 +3,16 @@ pragma solidity >=0.8.26; interface ICyphernodeRegistry { /// @notice This event MUST be emitted when a committee is selected for an E3. + /// @param e3Id ID of the E3 for which the committee was selected. + /// @param pools Addresses of the pools of nodes from which the committee was selected. + /// @param threshold The M/N threshold for the committee. event CommitteeRequested(uint256 indexed e3Id, address[] pools, uint32[2] threshold); + /// @notice This event MUST be emitted when a committee is selected for an E3. + /// @param e3Id ID of the E3 for which the committee was selected. + /// @param nodes Addresses of the nodes in the committee. + /// @param merkleRoots Merkle roots of the nodes in the committee. + /// @param publicKey Public key of the committee. event CommitteeSelected( uint256 indexed e3Id, address[] nodes,