diff --git a/.gitignore b/.gitignore index 027050ef..801dc1a8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ out/ .vscode/ deploy-config/* !deploy-config/deploy-config-holesky-testnet.toml +!deploy-config/exmp-dg-setup-deploy-config-holesky.toml # dev/testnet deployments !deploy-config/deployment-* diff --git a/addresses/holesky-addresses.sol b/addresses/holesky-addresses.sol deleted file mode 100644 index 6f052252..00000000 --- a/addresses/holesky-addresses.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -address constant DAO_VOTING = 0xdA7d2573Df555002503F29aA4003e398d28cc00f; -address constant ST_ETH = 0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034; -address constant WST_ETH = 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D; -address constant WITHDRAWAL_QUEUE = 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50; diff --git a/addresses/mainnet-addresses.sol b/addresses/mainnet-addresses.sol deleted file mode 100644 index 8d9643f9..00000000 --- a/addresses/mainnet-addresses.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -address constant DAO_ACL = 0x9895F0F17cc1d1891b6f18ee0b483B6f221b37Bb; -address constant DAO_AGENT = 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c; -address constant DAO_VOTING = 0x2e59A20f205bB85a89C53f1936454680651E618e; -address constant DAO_TOKEN_MANAGER = 0xf73a1260d222f447210581DDf212D915c09a3249; -address constant ST_ETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; -address constant WST_ETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; -address constant LDO_TOKEN = 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32; -address constant WITHDRAWAL_QUEUE = 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1; -address constant BURNER = 0xD15a672319Cf0352560eE76d9e89eAB0889046D3; diff --git a/contracts/DualGovernance.sol b/contracts/DualGovernance.sol index 12a73b7b..d25c21d8 100644 --- a/contracts/DualGovernance.sol +++ b/contracts/DualGovernance.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -299,8 +300,8 @@ contract DualGovernance is IDualGovernance { _stateMachine.activateNextState(); } - /// @notice Updates the address of the configuration provider for the Dual Governance system. - /// @param newConfigProvider The address of the new configuration provider contract. + /// @notice Sets the configuration provider for the Dual Governance system. + /// @param newConfigProvider The contract implementing the `IDualGovernanceConfigProvider` interface. function setConfigProvider(IDualGovernanceConfigProvider newConfigProvider) external { _checkCallerIsAdminExecutor(); _stateMachine.setConfigProvider(newConfigProvider); @@ -319,14 +320,14 @@ contract DualGovernance is IDualGovernance { emit ProposalsCancellerSet(newProposalsCanceller); } - /// @notice Retrieves the current proposals canceller address. + /// @notice Returns the current proposals canceller address. /// @return address The address of the current proposals canceller. function getProposalsCanceller() external view returns (address) { return _proposalsCanceller; } - /// @notice Returns the current configuration provider address for the Dual Governance system. - /// @return configProvider The address of the current configuration provider contract. + /// @notice Returns the current configuration provider for the Dual Governance system. + /// @return configProvider The contract implementing the `IDualGovernanceConfigProvider` interface. function getConfigProvider() external view returns (IDualGovernanceConfigProvider) { return _stateMachine.configProvider; } @@ -412,7 +413,7 @@ contract DualGovernance is IDualGovernance { } /// @notice Returns the proposer data if the given `proposerAccount` is a registered proposer. - /// @param proposerAccount The address of the proposer to retrieve information for. + /// @param proposerAccount The address of the proposer to return information for. /// @return proposer A Proposer struct containing the data of the registered proposer, including: /// - `account`: The address of the registered proposer. /// - `executor`: The address of the executor associated with the proposer. @@ -426,7 +427,7 @@ contract DualGovernance is IDualGovernance { proposers = _proposers.getAllProposers(); } - /// @notice Checks whether the given `proposerAccount` is a registered proposer. + /// @notice Returns whether the given `proposerAccount` is a registered proposer. /// @param proposerAccount The address to check. /// @return isProposer A boolean value indicating whether the `proposerAccount` is a registered /// proposer (`true`) or not (`false`). @@ -434,7 +435,7 @@ contract DualGovernance is IDualGovernance { return _proposers.isRegisteredProposer(proposerAccount); } - /// @notice Checks whether the given `executor` address is associated with an executor contract in the system. + /// @notice Returns whether the given `executor` address is associated with an executor contract in the system. /// @param executor The address to check. /// @return isExecutor A boolean value indicating whether the `executor` is a registered /// executor (`true`) or not (`false`). @@ -536,20 +537,20 @@ contract DualGovernance is IDualGovernance { _resealer.setResealCommittee(newResealCommittee); } - /// @notice Sets the address of the Reseal Manager. - /// @param newResealManager The address of the new Reseal Manager. + /// @notice Sets the address of the Reseal Manager contract. + /// @param newResealManager The contract implementing the `IResealManager` interface. function setResealManager(IResealManager newResealManager) external { _checkCallerIsAdminExecutor(); _resealer.setResealManager(newResealManager); } - /// @notice Gets the address of the Reseal Manager. - /// @return resealManager The address of the Reseal Manager. + /// @notice Returns the address of the Reseal Manager contract. + /// @return resealManager The contract implementing the `IResealManager` interface. function getResealManager() external view returns (IResealManager) { return _resealer.resealManager; } - /// @notice Gets the address of the reseal committee. + /// @notice Returns the address of the reseal committee. /// @return resealCommittee The address of the reseal committee. function getResealCommittee() external view returns (address) { return _resealer.resealCommittee; diff --git a/contracts/EmergencyProtectedTimelock.sol b/contracts/EmergencyProtectedTimelock.sol index 2861c658..5e634f0d 100644 --- a/contracts/EmergencyProtectedTimelock.sol +++ b/contracts/EmergencyProtectedTimelock.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -12,10 +13,25 @@ import {TimelockState} from "./libraries/TimelockState.sol"; import {ExecutableProposals} from "./libraries/ExecutableProposals.sol"; import {EmergencyProtection} from "./libraries/EmergencyProtection.sol"; -/// @title EmergencyProtectedTimelock -/// @dev A timelock contract with emergency protection functionality. The contract allows for submitting, scheduling, -/// and executing proposals, while providing emergency protection features to prevent unauthorized execution during -/// emergency situations. +/// @notice Timelock contract facilitating the submission, scheduling, and execution of governance proposals. +/// It provides time-limited Emergency Protection to prevent the execution of proposals submitted by +/// a compromised or misbehaving (including those caused by code vulnerabilities) governance entity. +/// @dev The proposal lifecycle: +/// +/// afterSubmitDelay afterScheduleDelay +/// passed passed +/// ┌──────────┐ ┌───────────┐ ┌───────────┐ ╔══════════╗ +/// │ NotExist ├ submit() ─>│ Submitted ├ schedule() ─>│ Scheduled ├ execute() ─>║ Executed ║ +/// └──────────┘ └────────┬──┘ └──┬────────┘ ╚══════════╝ +/// cancelAllNonExecutedProposals() +/// │ ╔═══════════╗ │ +/// └──>║ Cancelled ║<───┘ +/// ╚═══════════╝ +/// +/// The afterSubmit and afterSchedule delays should be configured appropriately to provide the Emergency Activation +/// Committee sufficient time to activate Emergency Mode if a malicious proposal has been submitted or was +/// unexpectedly scheduled for execution due to governance capture or a vulnerability in the governance contract. +/// While Emergency Mode is active, the execution of proposals is restricted to the Emergency Execution Committee. contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock { using TimelockState for TimelockState.Context; using ExecutableProposals for ExecutableProposals.Context; @@ -134,7 +150,7 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock { // Timelock Management // --- - /// @notice Updates the address of the governance contract. + /// @notice Updates the address of the governance contract and cancels all non-executed proposals. /// @param newGovernance The address of the new governance contract to be set. function setGovernance(address newGovernance) external { _timelockState.checkCallerIsAdminExecutor(); @@ -308,7 +324,7 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock { return _timelockState.getAfterScheduleDelay(); } - /// @notice Retrieves the details of a proposal. + /// @notice Returns the details of a proposal. /// @param proposalId The id of the proposal. /// @return proposalDetails The Proposal struct containing the details of the proposal. /// @return calls An array of ExternalCall structs representing the sequence of calls to be executed for the proposal. @@ -321,12 +337,11 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock { calls = _proposals.getProposalCalls(proposalId); } - /// @notice Retrieves information about a proposal, excluding the external calls associated with it. - /// @param proposalId The id of the proposal to retrieve information for. + /// @notice Returns information about a proposal, excluding the external calls associated with it. + /// @param proposalId The id of the proposal to return information for. /// @return proposalDetails A ProposalDetails struct containing the details of the proposal, with the following data: /// - `id`: The id of the proposal. /// - `status`: The current status of the proposal. Possible values are: - /// 0 - The proposal does not exist. /// 1 - The proposal was submitted but not scheduled. /// 2 - The proposal was submitted and scheduled but not yet executed. /// 3 - The proposal was submitted, scheduled, and executed. This is the final state of the proposal lifecycle. @@ -340,14 +355,14 @@ contract EmergencyProtectedTimelock is IEmergencyProtectedTimelock { return _proposals.getProposalDetails(proposalId); } - /// @notice Retrieves the external calls associated with the specified proposal. - /// @param proposalId The id of the proposal to retrieve external calls for. + /// @notice Returns the external calls associated with the specified proposal. + /// @param proposalId The id of the proposal to return external calls for. /// @return calls An array of ExternalCall structs representing the sequence of calls to be executed for the proposal. function getProposalCalls(uint256 proposalId) external view returns (ExternalCall[] memory calls) { calls = _proposals.getProposalCalls(proposalId); } - /// @notice Retrieves the total number of proposals. + /// @notice Returns the total number of proposals. /// @return count The total number of proposals. function getProposalsCount() external view returns (uint256 count) { count = _proposals.getProposalsCount(); diff --git a/contracts/Escrow.sol b/contracts/Escrow.sol index 12d044e7..495474b0 100644 --- a/contracts/Escrow.sol +++ b/contracts/Escrow.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -145,7 +146,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { ST_ETH.approve(address(WITHDRAWAL_QUEUE), type(uint256).max); } - /// @notice Retrieves the current state of the Escrow. + /// @notice Returns the current state of the Escrow. /// @return State The current state of the Escrow. function getEscrowState() external view returns (State) { return _escrowState.state; @@ -305,7 +306,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { // --- /// @notice Sets the minimum duration that must elapse after the last stETH, wstETH, or unstETH lock - /// by a vetoer before they are permitted to unlock their assets from the Escrow. + /// by a vetoer before they are permitted to unlock their assets from the Signalling Escrow. /// @param newMinAssetsLockDuration The new minimum lock duration to be set. function setMinAssetsLockDuration(Duration newMinAssetsLockDuration) external { _checkCallerIsDualGovernance(); @@ -353,7 +354,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { details.lastAssetsLockTimestamp = assets.lastAssetsLockTimestamp; } - // @notice Retrieves the unstETH NFT ids of the specified vetoer. + /// @notice Returns the unstETH NFT ids of the specified vetoer. /// @param vetoer The address of the vetoer whose unstETH NFTs are being queried. /// @return unstETHIds An array of unstETH NFT ids locked by the vetoer. function getVetoerUnstETHIds(address vetoer) external view returns (uint256[] memory unstETHIds) { @@ -376,8 +377,8 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { details.totalUnstETHFinalizedETH = unstETHTotals.finalizedETH; } - /// @notice Retrieves details of locked unstETH records for the given ids. - /// @param unstETHIds The array of ids for the unstETH records to retrieve. + /// @notice Returns details of locked unstETH records for the given ids. + /// @param unstETHIds The array of ids for the unstETH records to return. /// @return unstETHDetails An array of `LockedUnstETHDetails` containing the details for each provided unstETH id. /// /// The details include: @@ -568,7 +569,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { // Rage Quit Escrow: Getters // --- - /// @notice Retrieves the unstETH NFT ids of the next batch available for claiming. + /// @notice Returns the unstETH NFT ids of the next batch available for claiming. /// @param limit The maximum number of unstETH NFTs to return in the batch. /// @return unstETHIds An array of unstETH NFT ids available for the next withdrawal batch. function getNextWithdrawalBatch(uint256 limit) external view returns (uint256[] memory unstETHIds) { @@ -598,7 +599,7 @@ contract Escrow is ISignallingEscrow, IRageQuitEscrow { return _escrowState.isRageQuitExtensionPeriodPassed(); } - /// @notice Retrieves details about the current state of the rage quit escrow. + /// @notice Returns details about the current state of the rage quit escrow. /// @return details A `RageQuitEscrowDetails` struct containing the following fields: /// - `isRageQuitExtensionPeriodStarted`: Indicates whether the rage quit extension period has started. /// - `rageQuitEthWithdrawalsDelay`: The delay period for ETH withdrawals during rage quit. diff --git a/contracts/Executor.sol b/contracts/Executor.sol index dd649fc5..fee9e178 100644 --- a/contracts/Executor.sol +++ b/contracts/Executor.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/ImmutableDualGovernanceConfigProvider.sol b/contracts/ImmutableDualGovernanceConfigProvider.sol index 13cb5876..f8e158d4 100644 --- a/contracts/ImmutableDualGovernanceConfigProvider.sol +++ b/contracts/ImmutableDualGovernanceConfigProvider.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -18,11 +19,11 @@ contract ImmutableDualGovernanceConfigProvider is IDualGovernanceConfigProvider // Immutable Variables // --- - /// @notice The percentage of the total stETH supply that must be exceeded in the Signalling Escrow to transition + /// @notice The percentage of the total stETH supply that must be reached in the Signalling Escrow to transition /// Dual Governance from the Normal state to the VetoSignalling state. PercentD16 public immutable FIRST_SEAL_RAGE_QUIT_SUPPORT; - /// @notice The percentage of the total stETH supply that must be exceeded in the Signalling Escrow to transition + /// @notice The percentage of the total stETH supply that must be reached in the Signalling Escrow to transition /// Dual Governance into the RageQuit state. PercentD16 public immutable SECOND_SEAL_RAGE_QUIT_SUPPORT; diff --git a/contracts/ResealManager.sol b/contracts/ResealManager.sol index 88f407b9..598dbb69 100644 --- a/contracts/ResealManager.sol +++ b/contracts/ResealManager.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -29,7 +30,7 @@ contract ResealManager is IResealManager { // --- /// @notice Initializes the ResealManager contract. - /// @param emergencyProtectedTimelock The address of the EmergencyProtectedTimelock contract. + /// @param emergencyProtectedTimelock The address of the Timelock contract. constructor(ITimelock emergencyProtectedTimelock) { EMERGENCY_PROTECTED_TIMELOCK = emergencyProtectedTimelock; } @@ -40,7 +41,7 @@ contract ResealManager is IResealManager { /// @notice Extends the pause of the specified sealable contract. /// @dev Works only if conditions are met: - /// - ResealManager has PAUSE_ROLE for target contract; + /// - ResealManager has PAUSE_ROLE and RESUME_ROLE for target contract; /// - Contract are paused until timestamp after current timestamp and not for infinite time; /// - The DAO governance is blocked by DualGovernance; /// - Function is called by the governance contract. diff --git a/contracts/TimelockedGovernance.sol b/contracts/TimelockedGovernance.sol index 348d927e..64744417 100644 --- a/contracts/TimelockedGovernance.sol +++ b/contracts/TimelockedGovernance.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/committees/HashConsensus.sol b/contracts/committees/HashConsensus.sol index 387616d7..8d8ddc08 100644 --- a/contracts/committees/HashConsensus.sol +++ b/contracts/committees/HashConsensus.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/committees/ProposalsList.sol b/contracts/committees/ProposalsList.sol index 2a01b0b3..bb69983a 100644 --- a/contracts/committees/ProposalsList.sol +++ b/contracts/committees/ProposalsList.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/committees/TiebreakerCoreCommittee.sol b/contracts/committees/TiebreakerCoreCommittee.sol index 9fb873cd..6013f481 100644 --- a/contracts/committees/TiebreakerCoreCommittee.sol +++ b/contracts/committees/TiebreakerCoreCommittee.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/committees/TiebreakerSubCommittee.sol b/contracts/committees/TiebreakerSubCommittee.sol index 00fe623f..9cde60a1 100644 --- a/contracts/committees/TiebreakerSubCommittee.sol +++ b/contracts/committees/TiebreakerSubCommittee.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IDualGovernance.sol b/contracts/interfaces/IDualGovernance.sol index 336b1d82..d1a6cc09 100644 --- a/contracts/interfaces/IDualGovernance.sol +++ b/contracts/interfaces/IDualGovernance.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IDualGovernanceConfigProvider.sol b/contracts/interfaces/IDualGovernanceConfigProvider.sol index e9c6988c..8531f03f 100644 --- a/contracts/interfaces/IDualGovernanceConfigProvider.sol +++ b/contracts/interfaces/IDualGovernanceConfigProvider.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IEmergencyProtectedTimelock.sol b/contracts/interfaces/IEmergencyProtectedTimelock.sol index 30139348..9be458f1 100644 --- a/contracts/interfaces/IEmergencyProtectedTimelock.sol +++ b/contracts/interfaces/IEmergencyProtectedTimelock.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IEscrowBase.sol b/contracts/interfaces/IEscrowBase.sol index c1e8f22e..6a696766 100644 --- a/contracts/interfaces/IEscrowBase.sol +++ b/contracts/interfaces/IEscrowBase.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IExternalExecutor.sol b/contracts/interfaces/IExternalExecutor.sol index 466c927c..2f51ea5d 100644 --- a/contracts/interfaces/IExternalExecutor.sol +++ b/contracts/interfaces/IExternalExecutor.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IGovernance.sol b/contracts/interfaces/IGovernance.sol index ebf31d6d..4a6a83f2 100644 --- a/contracts/interfaces/IGovernance.sol +++ b/contracts/interfaces/IGovernance.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IOwnable.sol b/contracts/interfaces/IOwnable.sol index 8ef5a4fa..dbf17574 100644 --- a/contracts/interfaces/IOwnable.sol +++ b/contracts/interfaces/IOwnable.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IRageQuitEscrow.sol b/contracts/interfaces/IRageQuitEscrow.sol index 6649db93..5e4259a8 100644 --- a/contracts/interfaces/IRageQuitEscrow.sol +++ b/contracts/interfaces/IRageQuitEscrow.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IResealManager.sol b/contracts/interfaces/IResealManager.sol index 844bd8e1..16a14fa5 100644 --- a/contracts/interfaces/IResealManager.sol +++ b/contracts/interfaces/IResealManager.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/ISealable.sol b/contracts/interfaces/ISealable.sol index 263a29ec..ea933655 100644 --- a/contracts/interfaces/ISealable.sol +++ b/contracts/interfaces/ISealable.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/ISignallingEscrow.sol b/contracts/interfaces/ISignallingEscrow.sol index fcdfcc43..c3540ab2 100644 --- a/contracts/interfaces/ISignallingEscrow.sol +++ b/contracts/interfaces/ISignallingEscrow.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IStETH.sol b/contracts/interfaces/IStETH.sol index 6b6719e7..6164995c 100644 --- a/contracts/interfaces/IStETH.sol +++ b/contracts/interfaces/IStETH.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/ITiebreaker.sol b/contracts/interfaces/ITiebreaker.sol index 9d4e89fa..05ef3dec 100644 --- a/contracts/interfaces/ITiebreaker.sol +++ b/contracts/interfaces/ITiebreaker.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/ITiebreakerCoreCommittee.sol b/contracts/interfaces/ITiebreakerCoreCommittee.sol index 6bcd1fba..079e9f0f 100644 --- a/contracts/interfaces/ITiebreakerCoreCommittee.sol +++ b/contracts/interfaces/ITiebreakerCoreCommittee.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/ITimelock.sol b/contracts/interfaces/ITimelock.sol index 234a000d..c2bdfc37 100644 --- a/contracts/interfaces/ITimelock.sol +++ b/contracts/interfaces/ITimelock.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IWithdrawalQueue.sol b/contracts/interfaces/IWithdrawalQueue.sol index 4f0a276c..d29431fb 100644 --- a/contracts/interfaces/IWithdrawalQueue.sol +++ b/contracts/interfaces/IWithdrawalQueue.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/interfaces/IWstETH.sol b/contracts/interfaces/IWstETH.sol index 557553ad..1e53ed67 100644 --- a/contracts/interfaces/IWstETH.sol +++ b/contracts/interfaces/IWstETH.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/AssetsAccounting.sol b/contracts/libraries/AssetsAccounting.sol index 214430a4..a7a647d4 100644 --- a/contracts/libraries/AssetsAccounting.sol +++ b/contracts/libraries/AssetsAccounting.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/DualGovernanceConfig.sol b/contracts/libraries/DualGovernanceConfig.sol index f4f95f5c..ad0cd7b8 100644 --- a/contracts/libraries/DualGovernanceConfig.sol +++ b/contracts/libraries/DualGovernanceConfig.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -24,9 +25,9 @@ library DualGovernanceConfig { // --- /// @notice Configuration values for Dual Governance. - /// @param firstSealRageQuitSupport The percentage of the total stETH supply that must be exceeded in the Signalling + /// @param firstSealRageQuitSupport The percentage of the total stETH supply that must be reached in the Signalling /// Escrow to transition Dual Governance from the Normal state to the VetoSignalling state. - /// @param secondSealRageQuitSupport The percentage of the total stETH supply that must be exceeded in the + /// @param secondSealRageQuitSupport The percentage of the total stETH supply that must be reached in the /// Signalling Escrow to transition Dual Governance into the RageQuit state. /// /// @param minAssetsLockDuration The minimum duration that assets must remain locked in the Signalling Escrow contract diff --git a/contracts/libraries/DualGovernanceStateMachine.sol b/contracts/libraries/DualGovernanceStateMachine.sol index d384fc22..bd957577 100644 --- a/contracts/libraries/DualGovernanceStateMachine.sol +++ b/contracts/libraries/DualGovernanceStateMachine.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/DualGovernanceStateTransitions.sol b/contracts/libraries/DualGovernanceStateTransitions.sol index b7b78dc5..c5fdfacb 100644 --- a/contracts/libraries/DualGovernanceStateTransitions.sol +++ b/contracts/libraries/DualGovernanceStateTransitions.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -8,7 +9,25 @@ import {DualGovernanceConfig} from "./DualGovernanceConfig.sol"; import {State, DualGovernanceStateMachine} from "./DualGovernanceStateMachine.sol"; /// @title Dual Governance State Transitions Library -/// @notice Library containing the transitions logic for the Dual Governance system +/// @notice Library containing the transition logic for the Dual Governance system. +/// @dev The graph of the state transitions: +/// +/// ┌─────────────┐ ┌──────────────────┐ +/// │ Normal ├────>│ VetoSignalling │<───────┐ +/// ┌─>│ [SUB, EXE] │ │ [SUB] │<────┐ │ +/// │ └─────────────┘ │ ┌──────────────┐ │ │ │ +/// │ ┌──┼─┤ Deactivation ├─┼──┐ │ │ +/// │ │ │ │ [ ] │ │ │ │ │ +/// │ │ │ └──────────────┘ │ │ │ │ +/// │ │ └──────────────────┘ │ │ │ +/// │ ┌──────────────┐ │ ┌──────────┐ │ │ │ +/// └──┤ VetoCooldown │<┘ │ RageQuit │<──────┘ │ │ +/// │ [EXE] │<──────┤ [SUB] │<─────────┘ │ +/// └──────┬───────┘ └──────────┘ │ +/// └────────────────────────────────────────┘ +/// +/// SUB - Allows proposals submission while the state is active. +/// EXE - Allows scheduling proposals for execution while the state is active. library DualGovernanceStateTransitions { using DualGovernanceConfig for DualGovernanceConfig.Context; diff --git a/contracts/libraries/EmergencyProtection.sol b/contracts/libraries/EmergencyProtection.sol index 4543a79a..f6e1f302 100644 --- a/contracts/libraries/EmergencyProtection.sol +++ b/contracts/libraries/EmergencyProtection.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/EnumerableProposals.sol b/contracts/libraries/EnumerableProposals.sol index 18d9ce0f..b356ccf7 100644 --- a/contracts/libraries/EnumerableProposals.sol +++ b/contracts/libraries/EnumerableProposals.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/EscrowState.sol b/contracts/libraries/EscrowState.sol index 45fa5be4..c3b4707e 100644 --- a/contracts/libraries/EscrowState.sol +++ b/contracts/libraries/EscrowState.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/ExecutableProposals.sol b/contracts/libraries/ExecutableProposals.sol index e385f667..f34ba52c 100644 --- a/contracts/libraries/ExecutableProposals.sol +++ b/contracts/libraries/ExecutableProposals.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/ExternalCalls.sol b/contracts/libraries/ExternalCalls.sol index ace806b4..7848a09d 100644 --- a/contracts/libraries/ExternalCalls.sol +++ b/contracts/libraries/ExternalCalls.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/Proposers.sol b/contracts/libraries/Proposers.sol index a8fb4b17..07ae5278 100644 --- a/contracts/libraries/Proposers.sol +++ b/contracts/libraries/Proposers.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/Resealer.sol b/contracts/libraries/Resealer.sol index 4b176512..0f21c1c3 100644 --- a/contracts/libraries/Resealer.sol +++ b/contracts/libraries/Resealer.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/SealableCalls.sol b/contracts/libraries/SealableCalls.sol index 0a204811..e488d79c 100644 --- a/contracts/libraries/SealableCalls.sol +++ b/contracts/libraries/SealableCalls.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -19,7 +20,7 @@ library SealableCalls { /// If the value is less than `block.timestamp`, it indicates the contract resumed in the past; /// if `type(uint256).max`, the contract is paused indefinitely. function callGetResumeSinceTimestamp(address sealable) - external + internal view returns (bool success, uint256 resumeSinceTimestamp) { diff --git a/contracts/libraries/Tiebreaker.sol b/contracts/libraries/Tiebreaker.sol index 6c9772fd..a53c65d5 100644 --- a/contracts/libraries/Tiebreaker.sol +++ b/contracts/libraries/Tiebreaker.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/TimelockState.sol b/contracts/libraries/TimelockState.sol index 8abbbf35..9de8fa2e 100644 --- a/contracts/libraries/TimelockState.sol +++ b/contracts/libraries/TimelockState.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/libraries/WithdrawalsBatchesQueue.sol b/contracts/libraries/WithdrawalsBatchesQueue.sol index a84339d1..8f1c03a5 100644 --- a/contracts/libraries/WithdrawalsBatchesQueue.sol +++ b/contracts/libraries/WithdrawalsBatchesQueue.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/Duration.sol b/contracts/types/Duration.sol index 768f6698..1048f93d 100644 --- a/contracts/types/Duration.sol +++ b/contracts/types/Duration.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/ETHValue.sol b/contracts/types/ETHValue.sol index 9cf8f30b..ebed2a7e 100644 --- a/contracts/types/ETHValue.sol +++ b/contracts/types/ETHValue.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/IndexOneBased.sol b/contracts/types/IndexOneBased.sol index 538c0b90..36c98074 100644 --- a/contracts/types/IndexOneBased.sol +++ b/contracts/types/IndexOneBased.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/PercentD16.sol b/contracts/types/PercentD16.sol index 162ca6e6..5390443a 100644 --- a/contracts/types/PercentD16.sol +++ b/contracts/types/PercentD16.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/SharesValue.sol b/contracts/types/SharesValue.sol index a5aa466b..ac823403 100644 --- a/contracts/types/SharesValue.sol +++ b/contracts/types/SharesValue.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/contracts/types/Timestamp.sol b/contracts/types/Timestamp.sol index 7da52292..dad0c24d 100644 --- a/contracts/types/Timestamp.sol +++ b/contracts/types/Timestamp.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; diff --git a/deploy-artifacts/deploy-artifact-17000-1738139556.toml b/deploy-artifacts/deploy-artifact-17000-1738139556.toml new file mode 100644 index 00000000..f472f07c --- /dev/null +++ b/deploy-artifacts/deploy-artifact-17000-1738139556.toml @@ -0,0 +1,103 @@ +[deploy_config] +chain_id = 17000 + +[deploy_config.dual_governance] +admin_proposer = "0xdA7d2573Df555002503F29aA4003e398d28cc00f" +proposals_canceller = "0xdA7d2573Df555002503F29aA4003e398d28cc00f" +reseal_committee = "0x17A283c01dCc0F1d3D67b24E341e142DF78807D4" +sealable_withdrawal_blockers = ["0xF054E479b6A3D30CE70A4C4720988739BE362A55"] +tiebreaker_activation_timeout = 900 + +[deploy_config.dual_governance.sanity_check_params] +max_min_assets_lock_duration = 3600 +max_sealable_withdrawal_blockers_count = 255 +max_tiebreaker_activation_timeout = 1800 +min_tiebreaker_activation_timeout = 300 +min_withdrawals_batch_size = 1 + +[deploy_config.dual_governance.signalling_tokens] +st_eth = "0x7f6C35c096E1fdAa417B6A1C947Dc19F46a288cC" +withdrawal_queue = "0xF054E479b6A3D30CE70A4C4720988739BE362A55" +wst_eth = "0x80F767f445E97A4C6548D524D1429479cbb5FD2E" + +[deploy_config.dual_governance_config_provider] +first_seal_rage_quit_support = 300 +min_assets_lock_duration = 300 +rage_quit_eth_withdrawals_delay_growth = 1296000 +rage_quit_eth_withdrawals_max_delay = 1800 +rage_quit_eth_withdrawals_min_delay = 300 +rage_quit_extension_period_duration = 900 +second_seal_rage_quit_support = 1500 +veto_cooldown_duration = 900 +veto_signalling_deactivation_max_duration = 1800 +veto_signalling_max_duration = 1800 +veto_signalling_min_active_duration = 300 +veto_signalling_min_duration = 300 + +[deploy_config.tiebreaker] +committees_count = 3 +execution_delay = 900 +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[deploy_config.timelock] +after_schedule_delay = 900 +after_submit_delay = 900 + +[deploy_config.timelock.emergency_protection] +emergency_activation_committee = "0x8dA88a400500955E17FaB806DE606B025D033C66" +emergency_execution_committee = "0x7bAd309E8f1501C71f33dBbc843a462dAbF6Eb22" +emergency_governance_proposer = "0x17A283c01dCc0F1d3D67b24E341e142DF78807D4" +emergency_mode_duration = 86400 +emergency_protection_end_date = 1767225600 + +[deploy_config.timelock.sanity_check_params] +max_after_schedule_delay = 1800 +max_after_submit_delay = 1800 +max_emergency_mode_duration = 86400 +max_emergency_protection_duration = 31536000 +min_execution_delay = 300 + +[deployed_contracts] +admin_executor = "0xA275ddB4F0De13c4551de5f8d054F803C4E787B4" +dual_governance = "0xc2fA339ca250cA22beD862B4Dd38eFE159AF4cCe" +dual_governance_config_provider = "0xb27c0ff1137A84DA834DbD3c0741ECe440883793" +emergency_governance = "0x0DA61E4bC9E281B65BF213F50ebE0753b27b0CD2" +escrow_master_copy = "0x0000000000000000000000000000000000000000" +reseal_manager = "0x019c9bA97434EE94e3B3659E472aF2C38e025EFE" +tiebreaker_core_committee = "0xb448095d9556268e029a9E9c6f1Af514f12E4788" +tiebreaker_sub_committees = [ + "0xaCd2DD270Da868e877B49c0876BB0E15145622dF", + "0x730Bee80110752897Fb0923B94dbA0e02e26b72d", + "0x21ca18E7371E7A6C19CE77Ffe0b0DC29f40603b0", +] +timelock = "0xc8Df3f0dF91B4Dc9Bd366904e3e950b6600Aa576" diff --git a/deploy-artifacts/deploy-artifact-17000-1738145124.toml b/deploy-artifacts/deploy-artifact-17000-1738145124.toml new file mode 100644 index 00000000..35db98fd --- /dev/null +++ b/deploy-artifacts/deploy-artifact-17000-1738145124.toml @@ -0,0 +1,103 @@ +[deploy_config] +chain_id = 17000 + +[deploy_config.dual_governance] +admin_proposer = "0xdA7d2573Df555002503F29aA4003e398d28cc00f" +proposals_canceller = "0xdA7d2573Df555002503F29aA4003e398d28cc00f" +reseal_committee = "0x17A283c01dCc0F1d3D67b24E341e142DF78807D4" +sealable_withdrawal_blockers = ["0xC455F41f0A5a01359B6044b762A85B90324Ea5F0"] +tiebreaker_activation_timeout = 900 + +[deploy_config.dual_governance.sanity_check_params] +max_min_assets_lock_duration = 3600 +max_sealable_withdrawal_blockers_count = 255 +max_tiebreaker_activation_timeout = 1800 +min_tiebreaker_activation_timeout = 300 +min_withdrawals_batch_size = 1 + +[deploy_config.dual_governance.signalling_tokens] +st_eth = "0xea403E925EA33DFB268047bFf224f1b1D4Fa3883" +withdrawal_queue = "0xC455F41f0A5a01359B6044b762A85B90324Ea5F0" +wst_eth = "0x32A81f4aA79b20239350F8Fd28d20Ad85FD2ecdD" + +[deploy_config.dual_governance_config_provider] +first_seal_rage_quit_support = 300 +min_assets_lock_duration = 300 +rage_quit_eth_withdrawals_delay_growth = 1296000 +rage_quit_eth_withdrawals_max_delay = 1800 +rage_quit_eth_withdrawals_min_delay = 300 +rage_quit_extension_period_duration = 900 +second_seal_rage_quit_support = 1500 +veto_cooldown_duration = 900 +veto_signalling_deactivation_max_duration = 1800 +veto_signalling_max_duration = 1800 +veto_signalling_min_active_duration = 300 +veto_signalling_min_duration = 300 + +[deploy_config.tiebreaker] +committees_count = 3 +execution_delay = 900 +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[[deploy_config.tiebreaker.committees]] +members = [ + "0x14df797E7910D320931016E87133D0977eCa3c54", + "0x6FD09F5b4341C79CBDf679bccC2394C6FD7D0016", + "0xe8B2097674daF8fC3DcCDDf05a2cBeF8253A4bAB", + "0x7Cd64b87251f793027590c34b206145c3aa362Ae", + "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", +] +quorum = 1 + +[deploy_config.timelock] +after_schedule_delay = 900 +after_submit_delay = 900 + +[deploy_config.timelock.emergency_protection] +emergency_activation_committee = "0x8dA88a400500955E17FaB806DE606B025D033C66" +emergency_execution_committee = "0x7bAd309E8f1501C71f33dBbc843a462dAbF6Eb22" +emergency_governance_proposer = "0x17A283c01dCc0F1d3D67b24E341e142DF78807D4" +emergency_mode_duration = 86400 +emergency_protection_end_date = 1767225600 + +[deploy_config.timelock.sanity_check_params] +max_after_schedule_delay = 1800 +max_after_submit_delay = 1800 +max_emergency_mode_duration = 86400 +max_emergency_protection_duration = 31536000 +min_execution_delay = 300 + +[deployed_contracts] +admin_executor = "0xD5EE9991f44b36E186A658dc2A0357EcCf11b69B" +dual_governance = "0xb291a7f092D5cCE0A3C93eA21Bda3431129dB202" +dual_governance_config_provider = "0x957Fe85d9f7f17eba9D51dd212C5451Cc9354E83" +emergency_governance = "0x2D99B1Fe6AFA9d102C7125908081414b5C3Cc759" +escrow_master_copy = "0x0000000000000000000000000000000000000000" +reseal_manager = "0xc2764655e3fe0bd2D3C710D74Fa5a89162099FD8" +tiebreaker_core_committee = "0xDdC89Bd27F9A1C47A5c20dF0783dE52f55513598" +tiebreaker_sub_committees = [ + "0x2c0D8a145F39e2077b80aea41b5bf0Fa5342Ae39", + "0xB2Ace66d44B3CcD10096ab9C7E6556a85C27b27a", + "0xd256Dc67e318c53BAD904B48EDC1baCbE211A465", +] +timelock = "0x9404Fc6F57B32a01F4f8770F06B399C753519fC3" diff --git a/deploy-config/deployment-1737023280/deploy-artifact-holesky-mocks-1737023280.json b/deploy-config/deployment-1737023280/deploy-artifact-holesky-mocks-1737023280.json index 412d4d78..7d802cf8 100644 --- a/deploy-config/deployment-1737023280/deploy-artifact-holesky-mocks-1737023280.json +++ b/deploy-config/deployment-1737023280/deploy-artifact-holesky-mocks-1737023280.json @@ -9,78 +9,78 @@ "RESEAL_MANAGER": "0x632c29848A379a7B30Ee6461ea5e7e1e92d264d0", "TEMPORARY_EMERGENCY_GOVERNANCE": "0xc7467FeFF717C18db08BAEF252f11A84F48e8fF7", "TIEBREAKER_CORE_COMMITTEE": "0x6093B9b951C72498EE799639D74dC701Ead3f07B", - "TIEBREAKER_SUB_COMMITTEE_INFLUENCERS": "0x8F4b730099BFcA35fa4bbFD84f790eD34CAa246f", - "TIEBREAKER_SUB_COMMITTEE_NODE_OPERATORS": "0xBB259276147Af98c0e9186e783D4dbC26e82652F", - "TIEBREAKER_SUB_COMMITTEE_PROTOCOLS": "0x485349eBc3241e0bE8eDf7149C535c0b42Fa9504", + "TIEBREAKER_SUB_COMMITTEES": [ + "0x8F4b730099BFcA35fa4bbFD84f790eD34CAa246f", + "0xBB259276147Af98c0e9186e783D4dbC26e82652F", + "0x485349eBc3241e0bE8eDf7149C535c0b42Fa9504" + ], "TIMELOCK": "0x388AB7b65605e21a75Bb50E24a1eA43DD0091fa5", "DEPLOY_VERIFIER": "0xd67DF125fDC3360DeCB880804D1FA3Ae3fC6FFF1", - "chainName": "holesky-mocks", - "timestamp": 1737023280 + "DUAL_GOVERNANCE_CONFIG_PROVIDER": "0x71eB9e7b3EFCA08b2d483a46307b09f71B6175Ea" }, - "DUAL_GOVERNANCE_CONFIG": { - "EMERGENCY_ACTIVATION_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", - "EMERGENCY_EXECUTION_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", - "FIRST_SEAL_RAGE_QUIT_SUPPORT": 300, - "MAX_MIN_ASSETS_LOCK_DURATION": 3600, - "MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT": 255, - "MIN_ASSETS_LOCK_DURATION": 300, - "MIN_WITHDRAWALS_BATCH_SIZE": 1, - "RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH": 1296000, - "RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY": 1800, - "RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY": 300, - "RAGE_QUIT_EXTENSION_PERIOD_DURATION": 900, - "RESEAL_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", - "SECOND_SEAL_RAGE_QUIT_SUPPORT": 1500, - "VETO_COOLDOWN_DURATION": 900, - "VETO_SIGNALLING_DEACTIVATION_MAX_DURATION": 1800, - "VETO_SIGNALLING_MAX_DURATION": 1800, - "VETO_SIGNALLING_MIN_ACTIVE_DURATION": 300, - "VETO_SIGNALLING_MIN_DURATION": 300 - }, - "EMERGENCY_PROTECTED_TIMELOCK_CONFIG": { - "AFTER_SCHEDULE_DELAY": 900, - "AFTER_SUBMIT_DELAY": 900, - "EMERGENCY_MODE_DURATION": 900, - "EMERGENCY_PROTECTION_DURATION": 900, - "MAX_AFTER_SCHEDULE_DELAY": 1800, - "MAX_AFTER_SUBMIT_DELAY": 1800, - "MAX_EMERGENCY_MODE_DURATION": 1800, - "MAX_EMERGENCY_PROTECTION_DURATION": 1800, - "MIN_EXECUTION_DELAY": 300, - "TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566" - }, - "HOLESKY_MOCK_CONTRACTS": { - "DAO_VOTING": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", - "ST_ETH": "0x5C7B199956b976BB472a0AA2FaCC5DED425a1313", - "WITHDRAWAL_QUEUE": "0x2E22F14C5829Bd021911820f7408AD3b71a6584b", - "WST_ETH": "0x27C11A81B16526664D28a4222B0ee31704405B75" - }, - "TIEBREAKER_CONFIG": { - "ACTIVATION_TIMEOUT": 900, - "EXECUTION_DELAY": 900, - "INFLUENCERS": { - "MEMBERS": [ - "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566" - ], - "QUORUM": 1 - }, - "MAX_ACTIVATION_TIMEOUT": 1800, - "MIN_ACTIVATION_TIMEOUT": 300, - "NODE_OPERATORS": { - "MEMBERS": [ - "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566" - ], - "QUORUM": 1 + "DEPLOY_CONFIG": { + "CHAIN_ID": 17000, + "DUAL_GOVERNANCE": { + "ST_ETH": "0x5c7b199956b976bb472a0aa2facc5ded425a1313", + "WST_ETH": "0x27c11a81b16526664d28a4222b0ee31704405b75", + "UNST_ETH": "0x2e22f14c5829bd021911820f7408ad3b71a6584b", + "ADMIN_PROPOESER": "0xdA7d2573Df555002503F29aA4003e398d28cc00f", + "PROPOSALS_CANCELLER": "0xdA7d2573Df555002503F29aA4003e398d28cc00f", + "FIRST_SEAL_RAGE_QUIT_SUPPORT": 300, + "MAX_MIN_ASSETS_LOCK_DURATION": 3600, + "MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT": 255, + "MIN_ASSETS_LOCK_DURATION": 300, + "MIN_WITHDRAWALS_BATCH_SIZE": 1, + "RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH": 1296000, + "RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY": 1800, + "RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY": 300, + "RAGE_QUIT_EXTENSION_PERIOD_DURATION": 900, + "RESEAL_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", + "SECOND_SEAL_RAGE_QUIT_SUPPORT": 1500, + "VETO_COOLDOWN_DURATION": 900, + "VETO_SIGNALLING_DEACTIVATION_MAX_DURATION": 1800, + "VETO_SIGNALLING_MAX_DURATION": 1800, + "VETO_SIGNALLING_MIN_ACTIVE_DURATION": 300, + "VETO_SIGNALLING_MIN_DURATION": 300, + "SEALABLE_WITHDRAWAL_BLOCKERS": [ + "0x2E22F14C5829Bd021911820f7408AD3b71a6584b" + ] }, - "PROTOCOLS": { - "MEMBERS": [ - "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566" - ], - "QUORUM": 1 + "EMERGENCY_PROTECTED_TIMELOCK": { + "AFTER_SCHEDULE_DELAY": 900, + "AFTER_SUBMIT_DELAY": 900, + "EMERGENCY_MODE_DURATION": 900, + "EMERGENCY_PROTECTION_END_DATE": 1737024180, + "MAX_AFTER_SCHEDULE_DELAY": 1800, + "MAX_AFTER_SUBMIT_DELAY": 1800, + "MAX_EMERGENCY_MODE_DURATION": 1800, + "MAX_EMERGENCY_PROTECTION_DURATION": 1800, + "MIN_EXECUTION_DELAY": 300, + "EMERGENCY_GOVERNANCE_PROPOSER": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", + "EMERGENCY_ACTIVATION_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566", + "EMERGENCY_EXECUTION_COMMITTEE": "0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566" }, - "QUORUM": 1, - "SEALABLE_WITHDRAWAL_BLOCKERS": [ - "0x2E22F14C5829Bd021911820f7408AD3b71a6584b" - ] + "TIEBREAKER": { + "QUORUM": 1, + "ACTIVATION_TIMEOUT": 900, + "EXECUTION_DELAY": 900, + "MAX_ACTIVATION_TIMEOUT": 1800, + "MIN_ACTIVATION_TIMEOUT": 300, + "COMMITTEES_COUNT": 3, + "COMMITTEES": [ + { + "MEMBERS": ["0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566"], + "QUORUM": 1 + }, + { + "MEMBERS": ["0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566"], + "QUORUM": 1 + }, + { + "MEMBERS": ["0x526d46eCa1d7969924e981ecDbcAa74e9f0EE566"], + "QUORUM": 1 + } + ] + } } -} \ No newline at end of file +} diff --git a/deploy-config/deployment-1737023280/deploy-config-holesky-mocks-1737023280.toml b/deploy-config/deployment-1737023280/deploy-config-holesky-mocks-1737023280.toml index f28b392d..a44e9c1c 100644 --- a/deploy-config/deployment-1737023280/deploy-config-holesky-mocks-1737023280.toml +++ b/deploy-config/deployment-1737023280/deploy-config-holesky-mocks-1737023280.toml @@ -1,3 +1,11 @@ +CHAIN_ID = 17000 + +[LIDO_CONTRACTS] +ST_ETH = "0x5c7b199956b976bb472a0aa2facc5ded425a1313" +WST_ETH = "0x27c11a81b16526664d28a4222b0ee31704405b75" +WITHDRAWAL_QUEUE = "0x2e22f14c5829bd021911820f7408ad3b71a6584b" + + [EMERGENCY_PROTECTED_TIMELOCK_CONFIG] MIN_EXECUTION_DELAY = 300 AFTER_SUBMIT_DELAY = 900 @@ -8,12 +16,20 @@ EMERGENCY_MODE_DURATION = 900 MAX_EMERGENCY_MODE_DURATION = 1800 EMERGENCY_PROTECTION_DURATION = 900 MAX_EMERGENCY_PROTECTION_DURATION = 1800 + +# Temporary Governance +EMERGENCY_GOVERNANCE_PROPOSER = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" + +# TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" -[DUAL_GOVERNANCE_CONFIG] EMERGENCY_ACTIVATION_COMMITTEE = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" EMERGENCY_EXECUTION_COMMITTEE = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" + +[DUAL_GOVERNANCE_CONFIG] +ADMIN_PROPOESER = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" RESEAL_COMMITTEE = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +PROPOSALS_CANCELLER = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" MIN_WITHDRAWALS_BATCH_SIZE = 1 MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT = 255 FIRST_SEAL_RAGE_QUIT_SUPPORT = 300 @@ -30,28 +46,22 @@ RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY = 300 RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY = 1800 RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH = 1296000 -[HOLESKY_MOCK_CONTRACTS] -ST_ETH = "0x5c7b199956b976bb472a0aa2facc5ded425a1313" -WST_ETH = "0x27c11a81b16526664d28a4222b0ee31704405b75" -WITHDRAWAL_QUEUE = "0x2e22f14c5829bd021911820f7408ad3b71a6584b" -DAO_VOTING = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" - [TIEBREAKER_CONFIG] +QUORUM = 1 EXECUTION_DELAY = 900 MIN_ACTIVATION_TIMEOUT = 300 ACTIVATION_TIMEOUT = 900 MAX_ACTIVATION_TIMEOUT = 1800 -QUORUM = 1 SEALABLE_WITHDRAWAL_BLOCKERS = ["0x2e22f14c5829bd021911820f7408ad3b71a6584b"] -[TIEBREAKER_CONFIG.INFLUENCERS] -MEMBERS = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] +[[TIEBREAKER_CONFIG.COMMITTEES]] # Influencers QUORUM = 1 - -[TIEBREAKER_CONFIG.NODE_OPERATORS] MEMBERS = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] -QUORUM = 1 -[TIEBREAKER_CONFIG.PROTOCOLS] +[[TIEBREAKER_CONFIG.COMMITTEES]] # Node Operators +QUORUM = 1 MEMBERS = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] + +[[TIEBREAKER_CONFIG.COMMITTEES]] # Protocols QUORUM = 1 +MEMBERS = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] diff --git a/deploy-config/exmp-dg-setup-deploy-config-holesky.toml b/deploy-config/exmp-dg-setup-deploy-config-holesky.toml new file mode 100644 index 00000000..b545036b --- /dev/null +++ b/deploy-config/exmp-dg-setup-deploy-config-holesky.toml @@ -0,0 +1,81 @@ +chain_id = 17000 + +# ====================== +# DUAL GOVERNANCE CONFIG +# ====================== + +[dual_governance] +admin_proposer = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +reseal_committee = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +proposals_canceller = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +tiebreaker_activation_timeout = 900 +sealable_withdrawal_blockers = ["0x2e22f14c5829bd021911820f7408ad3b71a6584b"] + +[dual_governance.signalling_tokens] +st_eth = "0x5c7b199956b976bb472a0aa2facc5ded425a1313" +wst_eth = "0x27c11a81b16526664d28a4222b0ee31704405b75" +withdrawal_queue = "0x2e22f14c5829bd021911820f7408ad3b71a6584b" + +[dual_governance.sanity_check_params] +min_withdrawals_batch_size = 1 +max_tiebreaker_activation_timeout = 1800 +min_tiebreaker_activation_timeout = 300 +max_sealable_withdrawal_blockers_count = 255 +max_min_assets_lock_duration = 3600 + +[dual_governance_config_provider] +first_seal_rage_quit_support = 300 +second_seal_rage_quit_support = 1500 +min_assets_lock_duration = 300 +veto_signalling_min_duration = 300 +veto_signalling_min_active_duration = 300 +veto_signalling_max_duration = 1800 +veto_signalling_deactivation_max_duration = 1800 +veto_cooldown_duration = 900 +rage_quit_extension_period_duration = 900 +rage_quit_eth_withdrawals_min_delay = 300 +rage_quit_eth_withdrawals_max_delay = 1800 +rage_quit_eth_withdrawals_delay_growth = 1296000 + +# ====================== +# EMERGENCY PROTECTED TIMELOCK CONFIG +# ====================== + +[timelock] +after_submit_delay = 900 +after_schedule_delay = 900 + +[timelock.sanity_check_params] +min_execution_delay = 300 +max_after_submit_delay = 1800 +max_after_schedule_delay = 1800 +max_emergency_mode_duration = 86400 # 1 day +max_emergency_protection_duration = 31536000 # 1 year + +[timelock.emergency_protection] +emergency_mode_duration = 86400 # 1 day +emergency_protection_end_date = 1767225600 # Thu Jan 01 2026 00:00:00 GMT+0000 +emergency_governance_proposer = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +emergency_activation_committee = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" +emergency_execution_committee = "0x526d46eca1d7969924e981ecdbcaa74e9f0ee566" + +# ====================== +# TIEBREAKER CONFIG +# ====================== + +[tiebreaker] +quorum = 1 +committees_count = 3 +execution_delay = 900 + +[[tiebreaker.committees]] # Influencers +quorum = 1 +members = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] + +[[tiebreaker.committees]] # Node Operators +quorum = 1 +members = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] + +[[tiebreaker.committees]] # Protocols +quorum = 1 +members = ["0x526d46eca1d7969924e981ecdbcaa74e9f0ee566"] diff --git a/docs/known-risks-and-limitations.md b/docs/known-risks-and-limitations.md new file mode 100644 index 00000000..42199132 --- /dev/null +++ b/docs/known-risks-and-limitations.md @@ -0,0 +1,86 @@ +# Dual Governance: Known Risks & Limitations + +While the [Dual Governance (DG) system](specification.md) is designed to protect stETH holders from malicious DAO actions, certain protocol specifics and implementation details can reduce its effectiveness in certain situations. This document outlines key risks, limitations, and potential mitigation strategies. + + +## 1. Malicious Oracle Sets + +DG relies heavily on the Lido protocol’s [withdrawals mechanics](https://docs.lido.fi/guides/lido-tokens-integration-guide#withdrawals-unsteth), which in turn depend on the performance of the [accounting](https://docs.lido.fi/guides/oracle-spec/accounting-oracle) and [validators exit bus](https://docs.lido.fi/guides/oracle-spec/validator-exit-bus) oracles. + +A malicious set of oracle members could completely halt the withdrawal process. Combined with an ongoing RageQuit, this scenario could lock user funds in the Escrow contract and effectively paralyze governance. + +**Possible Mitigation:** + +If the Lido DAO acts in good faith, the Tiebreaker Committee can execute a proposal to remove malicious oracle members, thereby restoring the withdrawal finalization process. + +If the DAO itself is hostile, the only remaining solution will be the implementation of fully permissionless oracles or withdrawal processes. Early efforts toward this goal are already underway, including [negative rebase sanity checks with a second opinion](https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-23.md) and [triggerable exits](https://eips.ethereum.org/EIPS/eip-7002). + + +## 2. L2 & Side-Chains Bridges Pause + +The wstETH token is widely available on [many L2s and side-chains](https://docs.lido.fi/deployed-contracts/#lido-multichain). + +One recommended practice for these bridges is to implement [pausable deposits and withdrawals](https://docs.lido.fi/token-guides/wsteth-bridging-guide#r-7-pausable-deposits-and-withdrawals). + +Although the suggested approach is to combine [`GateSeals`](https://github.com/lidofinance/gate-seals) with a [`PausableUntil`](https://github.com/lidofinance/core/blob/master/contracts/0.8.9/utils/PausableUntil.sol) interface, most current bridges rely on a standard `Pausable` interface, which can pause contracts indefinitely by default. + +The proposed Dual Governance configuration assumes that pausing bridge deposits and withdrawals is protected by the Dual Governance mechanism, with the [Emergency Brakes multisigs](https://docs.lido.fi/multisigs/emergency-brakes) retaining the right to pause these bridges. + +Under the current pausability implementation, a malicious Emergency Brakes multisig could pause withdrawals indefinitely, preventing L2 wstETH holders from locking their funds in the Signalling escrow. + +**Possible Mitigation:** + +Adopting `GateSeal`-based pausing mechanisms would prevent an infinite pause by a single Emergency Brakes multisig. Such an attack would then require collusion with the Reseal Committee, significantly increasing the complexity of executing it. + + +## 3. stETH Availability & Thresholds Configuration + +The implementation of Dual Governance assumes that the first seal RageQuit threshold can be reached relatively quickly. If this threshold cannot be met during the VetoSignalling state (for example, because stETH is locked in L2s, CEXes, or other DeFi protocols), a malicious proposal might be executed before stETH holders can respond. + +**Possible Mitigation:** + +The initial Dual Governance parameters were chosen based on a several analytical researches. The chosen parameter values should be periodically recalibrated to reflect current market realities, guided by high-level models derived from these analyses. + + +## 4. Low TVL Periods + +When the protocol’s TVL is low, a malicious actor (for example, hostile LDO holders) controlling more than `100% - secondSealThreshold` of stETH TVL could prevent the initiation of RageQuit after submitting a harmful proposal. This scenario is more likely during later RageQuits, when a significant portion of stETH has already been withdrawn. + +**Possible Mitigation:** + +Users should be guided to exit earlier in the RageQuit sequence, when withdrawals are subject to shorter delays and the risk of losing funds due to the described attack is lower. + + +## 5. Misuse of the Signalling Escrow + +One of the main purposes of the Dual Governance mechanism in the Lido protocol is to: + +> Give stakers a say by allowing them to block DAO decisions and providing a negotiation device between stakers and the DAO. + +To ensure this feature is as accessible as possible for stETH holders, the current design **does not impose any penalties or reduce rewards for users who lock their stETH or wstETH in the Signalling Escrow**. + +The reasoning behind this decision is that expressing disagreement with a DAO proposal—without intending to leave the protocol—should not be punished. Penalizing dissent would discourage the active minority of stETH holders from participating in negotiations with the DAO. + +While this penalty-free approach encourages participation, it also allows for two potential misuse scenarios: + +1. **Unintentional Misuse:** Users might lock tokens indefinitely due to misunderstanding. +2. **Deliberate Misuse:** Malicious actors may lock tokens purely to stall DAO operations. + +These scenarios could keep Dual Governance perpetually cycling through `VetoSignalling`, `VetoSignallingDeactivation`, and `VetoCooldown` states. + +**Possible Mitigation:** + +Although both scenarios are possible, reaching the first seal threshold requires a substantial stETH commitment, resulting in high opportunity costs (lost yield opportunities for the locked tokens). This naturally deters casual misuse. + +The main mitigation lies in educating users about the Signalling Escrow’s intended purpose and ensuring that the user interface provides clear guidance. + +For deliberate misuse, no absolute protection exists. However, even in such cases, the DAO remains functional and can still operate, albeit more slowly. + + +## 6. The Undetermined Proposals Launch Time + +Due to variable Veto Signalling durations, DAO proposal execution times may vary, complicating time-sensitive actions. + +**Possible Mitigation:** + +Proposals can include time-validation check calls. See the [example `TimeConstraints` contract](https://github.com/lidofinance/dual-governance/blob/main/test/utils/time-constraints.sol) and its [usage example](https://github.com/lidofinance/dual-governance/blob/main/test/scenario/time-sensitive-proposal-execution.t.sol). diff --git a/docs/mechanism.md b/docs/mechanism.md index 2765edb5..acdefc7c 100644 --- a/docs/mechanism.md +++ b/docs/mechanism.md @@ -1,7 +1,3 @@ -**Working draft** - ---- - # Dual Governance mechanism design A proposal by [sam](https://twitter.com/_skozin), [pshe](https://twitter.com/PsheEth), [kadmil](https://twitter.com/kadmil_eth), [sacha](https://twitter.com/sachayve), [psirex](https://twitter.com/psirex_), [Hasu](https://twitter.com/hasufl), [Izzy](https://twitter.com/IsdrsP), and [Vasiliy](https://twitter.com/_vshapovalov). diff --git a/docs/plan-b.md b/docs/plan-b.md index c9268b7b..e475c5d9 100644 --- a/docs/plan-b.md +++ b/docs/plan-b.md @@ -4,41 +4,47 @@ Timelocked Governance (TG) is a governance subsystem positioned between the Lido > Motivation: the upcoming Ethereum upgrade *Pectra* will introduce a new [withdrawal mechanism](https://eips.ethereum.org/EIPS/eip-7002) (EIP-7002), significantly affecting the operation of the Lido protocol. This enhancement will allow withdrawal queue contract to trigger withdrawals, introducing a new attack vector for the whole protocol. This poses a threat to stETH users, as governance capture (or malicious actions) could enable an upgrade to the withdrawal queue contract, resulting in the theft of user funds. Timelocked Governance in its turn provides security assurances through the implementation of guardians (emergency committees) that can halt malicious proposals and the implementation of the timelock to ensure users and committees have sufficient time to react to potential threats. + ## Navigation -* [System overview](#system-overview) -* [Proposal flow](#proposal-flow) -* [Proposal execution](#proposal-execution) -* [Common types](#common-types) -* Contracts: - * [Contract: `TimelockedGovernance`](#contract-timelockedgovernance) - * [Contract: `EmergencyProtectedTimelock`](#contract-emergencyprotectedtimelock) - * [Contract: `Executor`](#contract-executor) + +- [System overview](#system-overview) +- [Proposal flow](#proposal-flow) +- [Proposal execution](#proposal-execution) +- [Common types](#common-types) +- Contracts: + - [Contract: `TimelockedGovernance`](#Contract-TimelockedGovernance) + - [Contract: `EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) + - [Contract: `Executor`](#Contract-Executor) + ## System Overview image The system comprises the following primary contracts: -- [**`TimelockedGovernance.sol`**](#contract-timelockedgovernance): A singleton contract that serves as the interface for submitting and scheduling the execution of governance proposals. -- [**`EmergencyProtectedTimelock.sol`**](#contract-emergencyprotectedtimelock): A singleton contract that stores submitted proposals and provides an execution interface. In addition, it implements an optional protection from a malicious proposals submitted by the DAO. The protection is implemented as a timelock on proposal execution combined with two emergency committees that have the right to cooperate and suspend the execution of the proposals. -- [**`Executor.sol`**](#contract-executor): A contract instance responsible for executing calls resulting from governance proposals. All protocol permissions or roles protected by TG, as well as the authority to manage these roles/permissions, should be assigned exclusively to instance of this contract, rather than being assigned directly to the DAO voting system. +- [`TimelockedGovernance`](#Contract-TimelockedGovernance): A singleton contract that serves as the interface for submitting and scheduling the execution of governance proposals. +- [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock): A singleton contract that stores submitted proposals and provides an execution interface. In addition, it implements an optional protection from a malicious proposals submitted by the DAO. The protection is implemented as a timelock on proposal execution combined with two emergency committees that have the right to cooperate and suspend the execution of the proposals. +- [`Executor`](#Contract-Executor): A contract instance responsible for executing calls resulting from governance proposals. All protocol permissions or roles protected by TG, as well as the authority to manage these roles/permissions, should be controlled exclusively by instance of this contract, rather than being assigned directly to the DAO voting system. ## Proposal flow + image The general proposal flow is as follows: -1. **Proposal Submission**: The Lido DAO submits a proposal via the admin voting system. This involves a set of external calls (represented by an array of [`ExecutorCall`] structs) to be executed by the [Admin Executor], by calling the [`TimelockedGovernance.submitProposal()`] function. -2. **After Submit Delay**: This initiates a preconfigured `AfterSubmitDelay` timelock period. Depending on the configuration, this period may be set to 0. If set to 0, the submitted proposal can be scheduled for execution immediately by anyone using the `TimelockGovernance.scheduleProposal()` method. -3. **Optional Proposal Cancellation**: At any moment before the proposal is executed, the Lido DAO may cancel all pending proposals using the `TimelockedGovernance.cancelAllPendingProposals` method. +1. **Proposal Submission**: The Lido DAO submits a proposal via the admin voting system. This involves a set of external calls (represented by an array of [`ExternalCall`](#Struct-ExternalCall) structs) to be executed by the **admin executor**, by calling the [`TimelockedGovernance.submitProposal`](#Function-TimelockedGovernancesubmitProposal) function. +2. **After Submit Delay**: This initiates a preconfigured `AfterSubmitDelay` timelock period. Depending on the configuration, this period may be set to 0. If set to 0, the submitted proposal can be scheduled for execution immediately by anyone using the [`TimelockGovernance.scheduleProposal`](#Function-TimelockedGovernancescheduleProposal) method. +3. **Optional Proposal Cancellation**: At any moment before the proposal is executed, the Lido DAO may cancel all pending proposals using the [`TimelockedGovernance.cancelAllPendingProposals`](#function-TimelockedGovernancecancelAllPendingProposals) method. 4. **Proposal Execution**: After the configured timelock has passed, the proposal may be executed, resulting in the proposal's calls being issued by the admin executor contract. + ## Proposal execution + image The proposal execution flow begins after the proposal is scheduled for execution and the `AfterScheduleDelay` has passed. -If emergency protection is enabled on the `EmergencyProtectedTimelock` instance, an **emergency activation committee** has a one-off, time-limited right to activate an adversarial **emergency mode** if they detect a malicious proposal submitted by the Lido DAO. +If emergency protection is enabled on the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) instance, an **emergency activation committee** has a one-off, time-limited right to activate an adversarial **emergency mode** if they detect a malicious proposal submitted by the Lido DAO. - Once the emergency mode is activated, the emergency activation committee is disabled, meaning it loses the ability to activate the emergency mode again. If the emergency activation committee doesn't activate the emergency mode within the **emergency protection duration** since the committee was configured, it gets automatically disabled as well. - The emergency mode lasts up to the **emergency mode max duration** from the moment of its activation. While it's active, only the **emergency execution committee** has the right to execute scheduled proposals. This committee also has a one-off right to **disable the emergency mode**. @@ -46,7 +52,7 @@ If emergency protection is enabled on the `EmergencyProtectedTimelock` instance, ## Common types -### Struct: ExternalCall +### Struct: `ExternalCall` ```solidity struct ExternalCall { @@ -58,45 +64,67 @@ struct ExternalCall { Encodes an external call from an executor contract to the `target` address with the specified `value` and the calldata being set to `payload`. +--- + ## Contract: `TimelockedGovernance` -The main entry point to the timelocked governance system, which provides an interface for submitting and canceling governance proposals in the `EmergencyProtectedTimelock` contract. This contract is a singleton, meaning that any TG deployment includes exactly one instance of this contract. +The main entry point to the timelocked governance system, which provides an interface for submitting and canceling governance proposals in the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) contract. This contract is a singleton, meaning that any TG deployment includes exactly one instance of this contract. + +--- ### Function: `TimelockedGovernance.submitProposal` + ```solidity function submitProposal(ExecutorCall[] calls, string metadata) returns (uint256 proposalId) ``` -Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance to register a new governance proposal composed of one or more external `calls`, along with the attached metadata text, to be made by an admin executor contract. Initiates a timelock on scheduling the proposal for execution. +Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance to register a new governance proposal composed of one or more external `calls`, along with the attached metadata text, to be made by an admin executor contract. Initiates a timelock on scheduling the proposal for execution. + +See: [`EmergencyProtectedTimelock.submit`](#Function-EmergencyProtectedTimelockSubmit) -See: [`EmergencyProtectedTimelock.submit`](#) #### Returns + The id of the successfully registered proposal. + #### Preconditions -* The `msg.sender` MUST be the address of the admin voting system + +- The `msg.sender` MUST be the address of the admin voting system + +--- ### Function: `TimelockedGovernance.scheduleProposal` + ```solidity -function scheduleProposal(uint256 proposalId) external +function scheduleProposal(uint256 proposalId) ``` -Instructs the [`EmergencyProtectedTimelock`](#) singleton instance to schedule the proposal with id `proposalId` for execution. -See: [`EmergencyProtectedTimelock.schedule`](#) +Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance to schedule the proposal with id `proposalId` for execution. + +See: [`EmergencyProtectedTimelock.schedule`](#Function-EmergencyProtectedTimelockSchedule) + #### Preconditions + - The proposal with the given id MUST be in the `Submitted` state. +--- ### Function: `TimelockedGovernance.executeProposal` + ```solidity -function executeProposal(uint256 proposalId) external +function executeProposal(uint256 proposalId) ``` -Instructs the [`EmergencyProtectedTimelock`](#) singleton instance to execute the proposal with id `proposalId`. -See: [`EmergencyProtectedTimelock.execute`](#) +Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance to execute the proposal with id `proposalId`. + +See: [`EmergencyProtectedTimelock.execute`](#Function-EmergencyProtectedTimelockExecute) + #### Preconditions + - The proposal with the given id MUST be in the `Scheduled` state. +--- + ### Function: `TimelockedGovernance.cancelAllPendingProposals` ```solidity @@ -105,78 +133,257 @@ function cancelAllPendingProposals() returns (bool) Cancels all currently submitted and non-executed proposals. If a proposal was submitted but not scheduled, it becomes unschedulable. If a proposal was scheduled, it becomes unexecutable. -The function will return `true` if all proposals are successfully canceled. If the subsequent call to the `EmergencyProtectedTimelock.cancelAllNonExecutedProposals()` method fails, the function will revert with an error. +The function will return `true` if all proposals are successfully canceled. If the subsequent call to the [`EmergencyProtectedTimelock.cancelAllNonExecutedProposals`](#Function-EmergencyProtectedTimelockcancelAllNonExecutedProposals) method fails, the function will revert with an error. -See: [`EmergencyProtectedTimelock.cancelAllNonExecutedProposals`](#) #### Preconditions -* MUST be called by an [admin voting system](#) +- MUST be called by an admin voting system + +--- ## Contract: `EmergencyProtectedTimelock` `EmergencyProtectedTimelock` is a singleton instance that stores and manages the lifecycle of proposals submitted by the DAO via the `TimelockedGovernance` contract. It can be configured with time-bound **Emergency Activation Committee** and **Emergency Execution Committee**, which act as safeguards against the execution of malicious proposals. For a proposal to be executed, the following steps have to be performed in order: -1. The proposal must be submitted using the `EmergencyProtectedTimelock.submit()` function. -2. The configured post-submit timelock (`EmergencyProtectedTimelock.getAfterSubmitDelay()`) must elapse. -3. The proposal must be scheduled using the `EmergencyProtectedTimelock.schedule()` function. -4. The configured emergency protection delay (`Configuration.getAfterScheduleDelay()`) must elapse (can be zero, see below). -5. The proposal must be executed using the `EmergencyProtectedTimelock.execute()` function. +1. The proposal must be submitted using the `EmergencyProtectedTimelock.submit` function. +2. The configured post-submit timelock (`EmergencyProtectedTimelock.getAfterSubmitDelay`) must elapse. +3. The proposal must be scheduled using the `EmergencyProtectedTimelock.schedule` function. +4. The configured emergency protection delay (`Configuration.getAfterScheduleDelay`) must elapse (can be zero, see below). +5. The proposal must be executed using the `EmergencyProtectedTimelock.execute` function. -The contract only allows proposal submission and scheduling by the `governance` address. Normally, this address points to the [`TimelockedGovernance`](#Contract-TimelockedGovernancesol) singleton instance. Proposal execution is permissionless, unless Emergency Mode is activated. +The contract only allows proposal submission and scheduling by the `governance` address. Normally, this address points to the [`TimelockedGovernance`](#Contract-TimelockedGovernance) singleton instance. Proposal execution is permissionless, unless Emergency Mode is activated. If the Emergency Committees are set up and active, the governance proposal undergoes a separate emergency protection delay between submission and scheduling. This additional timelock is implemented to protect against the execution of malicious proposals submitted by the DAO. If the Emergency Committees aren't set, the proposal flow remains the same, but the timelock duration is zero. - While active, the Emergency Activation Committee can enable Emergency Mode. This mode prohibits anyone but the Emergency Execution Committee from executing proposals. Once the **Emergency Duration** has ended, the Emergency Execution Committee or anyone else may disable the emergency mode, canceling all pending proposals. After the emergency mode is deactivated or the Emergency Period has elapsed, the Emergency Committees lose their power. +--- ### Function: `EmergencyProtectedTimelock.submit` + ```solidity -function submit(address proposer, address executor, ExecutorCall[] calls, string metadata) +function submit(address executor, ExternalCall[] calls) returns (uint256 proposalId) ``` -Registers a new governance proposal composed of one or more external `calls` to be made by the `executor` contract. Initiates the `AfterSubmitDelay`. + +Registers a new governance proposal consisting of one or more EVM `calls` to be executed by the specified `executor` contract. + #### Returns -The ID of the successfully registered proposal. + +The id of the successfully registered proposal. + #### Preconditions -* MUST be called by the `governance` address. + +- MUST be called by the `governance` address. +- The `calls` array length MUST be greater than zero. + +--- + ### Function: `EmergencyProtectedTimelock.schedule` + ```solidity function schedule(uint256 proposalId) ``` -Schedules the submitted proposal for execution. Initiates the `AfterScheduleDelay`. + +Schedules a previously submitted and non-cancelled proposal for execution after the required delay has passed. + #### Preconditions -* MUST be called by the `governance` address. -* The proposal MUST be in the `Submitted` state. -* The `AfterSubmitDelay` MUST already elapse since the moment the proposal was submitted. +- MUST be called by the `governance` address. +- The proposal MUST already be submitted. +- The post-submit timelock MUST have elapsed since the proposal submission. + +--- ### Function: `EmergencyProtectedTimelock.execute` + ```solidity function execute(uint256 proposalId) ``` + Instructs the executor contract associated with the proposal to issue the proposal's calls. + #### Preconditions -* Emergency mode MUST NOT be active. -* The proposal MUST be in the `Scheduled` state. -* The `AfterScheduleDelay` MUST already elapse since the moment the proposal was scheduled. + +- Emergency mode MUST NOT be active. +- The proposal MUST be already submitted & scheduled for execution. +- The emergency protection delay MUST already elapse since the moment the proposal was scheduled. + +--- ### Function: `EmergencyProtectedTimelock.cancelAllNonExecutedProposals` + ```solidity function cancelAllNonExecutedProposals() ``` -Cancels all non-executed proposals, making them permanently non-executable. + +Cancels all non-executed proposal, making them forever non-executable. + +#### Preconditions + +- MUST be called by the `governance` address. + +--- + +### Function: `EmergencyProtectedTimelock.setGovernance` + +```solidity +function setGovernance(address newGovernance) +``` + +Updates the address of the `governance` and cancels all non-executed proposals. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newGovernance` address MUST NOT be the zero address. +- The `newGovernance` address MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setAfterSubmitDelay` + +```solidity +function setAfterSubmitDelay(Duration newAfterSubmitDelay) +``` + +Sets the delay required between the submission of a proposal and its scheduling for execution. Ensures that the new delay value complies with the defined sanity check bounds. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newAfterSubmitDelay` duration MUST NOT exceed the `EmergencyProtectedTimelock.MAX_AFTER_SUBMIT_DELAY` value. +- The `newAfterSubmitDelay` duration MUST NOT be the same as the current value. +- After the update, the sum of `afterSubmitDelay` and `afterScheduleDelay` MUST NOT be less than the `EmergencyProtectedTimelock.MIN_EXECUTION_DELAY`. + +--- + +### Function: `EmergencyProtectedTimelock.setAfterScheduleDelay` + +```solidity +function setAfterScheduleDelay(Duration newAfterScheduleDelay) +``` + +Sets the delay required to pass from the scheduling of a proposal before it can be executed. Ensures that the new delay value complies with the defined sanity check bounds. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newAfterScheduleDelay` duration MUST NOT exceed the `EmergencyProtectedTimelock.MAX_AFTER_SCHEDULE_DELAY` value. +- The `newAfterScheduleDelay` duration MUST NOT be the same as the current value. +- After the update, the sum of `afterSubmitDelay` and `afterScheduleDelay` MUST NOT be less than the `EmergencyProtectedTimelock.MIN_EXECUTION_DELAY`. + +--- + +### Function: `EmergencyProtectedTimelock.transferExecutorOwnership` + +```solidity +function transferExecutorOwnership(address executor, address owner) +``` + +Transfers ownership of the specified executor contract to a new owner. + #### Preconditions -* MUST be called by the `governance` address. + +- MUST be called by the admin executor contract. +- The `executor` MUST implement the `IOwnable` interface. +- The current owner of the `executor` (`executor.owner`) MUST be the address of the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionActivationCommittee` + +```solidity +function setEmergencyProtectionActivationCommittee(address newEmergencyActivationCommittee) +``` + +Sets the address of the emergency activation committee. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyActivationCommittee` duration MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionExecutionCommittee` + +```solidity +function setEmergencyProtectionExecutionCommittee(address newEmergencyExecutionCommittee) +``` + +Sets the address of the emergency execution committee. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyExecutionCommittee` address MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionEndDate` + +```solidity +function setEmergencyProtectionEndDate(Timestamp newEmergencyProtectionEndDate) +``` + +Sets the end date for the emergency protection period. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyProtectionEndDate` MUST NOT be farther in the future than `EmergencyProtectedTimelock.MAX_EMERGENCY_PROTECTION_DURATION` from the `block.timestamp` at the time of method invocation. +- The `newEmergencyProtectionEndDate` MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyModeDuration` + +```solidity +function setEmergencyModeDuration(Duration newEmergencyModeDuration) +``` + +Sets the duration of the emergency mode. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyModeDuration` MUST NOT exceed the `EmergencyProtectedTimelock.MAX_EMERGENCY_MODE_DURATION` duration. +- The `newEmergencyModeDuration` MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyGovernance` + +```solidity +function setEmergencyGovernance(address newEmergencyGovernance) +``` + +Sets the address of the emergency governance contract. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyGovernance` address MUST NOT be the same as the current value. + +--- + ### Function: `EmergencyProtectedTimelock.activateEmergencyMode` + ```solidity function activateEmergencyMode() ``` + Activates the Emergency Mode. + #### Preconditions -* MUST be called by the active Emergency Activation Committee address. -* The Emergency Mode MUST NOT be active. + +- MUST be called by the Emergency Activation Committee address. +- The Emergency Mode MUST NOT be active. + +--- + ### Function: `EmergencyProtectedTimelock.emergencyExecute` ```solidity @@ -184,43 +391,268 @@ function emergencyExecute(uint256 proposalId) ``` Executes the scheduled proposal, bypassing the post-schedule delay. + #### Preconditions -* MUST be called by the Emergency Execution Committee address. -* The Emergency Mode MUST be active. + +- MUST be called by the Emergency Execution Committee address. +- The Emergency Mode MUST be active. + +--- + ### Function: `EmergencyProtectedTimelock.deactivateEmergencyMode` + ```solidity function deactivateEmergencyMode() ``` -Deactivates Emergency Mode, resets the Emergency Activation and Emergency Execution committees (setting their addresses to `0x00`), and cancels all unexecuted proposals. + +Deactivates the Emergency Activation and Emergency Execution Committees (setting their addresses to `0x00`), cancels all unexecuted proposals, and disables the [Protected deployment mode](#Proposal-execution-and-deployment-modes). + #### Preconditions -* The Emergency Mode MUST be active. -* If the Emergency Mode was activated less than the `emergency mode max duration` ago, MUST be called by the [Admin Executor](#) address. + +- The Emergency Mode MUST be active. +- If the Emergency Mode was activated less than the `emergency mode max duration` ago, MUST be called by the [Admin Executor](#Administrative-actions) address. + +--- + ### Function: `EmergencyProtectedTimelock.emergencyReset` + ```solidity function emergencyReset() ``` -Resets the `governance` address to the `EMERGENCY_GOVERNANCE` value defined in the configuration, deactivates the Emergency Mode, resets the Emergency Activation and Emergency Execution Committees (setting their addresses to `0x00`), and cancels all unexecuted proposals. + +Resets the `governance` address to the `EMERGENCY_GOVERNANCE` value defined in the configuration, cancels all unexecuted proposals, and disables the [Protected deployment mode](#Proposal-execution-and-deployment-modes). + #### Preconditions -* The Emergency Mode MUST be active. -* MUST be called by the Emergency Execution Committee address. -### Admin functions -The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setAfterSubmitDelay`, `setAfterScheduleDelay`). These functions MUST be called by the [Admin Executor](#) address. +- The Emergency Mode MUST be active. +- MUST be called by the Emergency Execution Committee address. -## Contract: `Executor` -Executes calls resulting from governance proposals' execution. Every protocol permission or role protected by the TG, as well as the permission to manage these roles/permissions, should be assigned exclusively to instances of this contract. +--- -The timelocked governance setup is designed to use a single admin instance of the `Executor`, which is owned by the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance. +### Function: `EmergencyProtectedTimelock.isEmergencyProtectionEnabled` + +```solidity +function isEmergencyProtectionEnabled() view returns (bool) +``` + +Returns whether emergency protection is currently enabled. + +--- + +### Function: `EmergencyProtectedTimelock.isEmergencyModeActive` + +```solidity +function isEmergencyModeActive() view returns (bool) +``` + +Returns whether the system is currently in Emergency Mode. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyProtectionDetails` + +```solidity +function getEmergencyProtectionDetails() view returns (EmergencyProtectionDetails memory details) +``` + +Returns details about the current state of emergency protection. The `EmergencyProtectionDetails` struct includes the following fields: + +- `emergencyModeDuration`: The duration for which the emergency mode remains active after activation. +- `emergencyModeEndsAfter`: The timestamp indicating when the current emergency mode will end. +- `emergencyProtectionEndsAfter`: The timestamp indicating when the overall emergency protection period will expire. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyGovernance` + +```solidity +function getEmergencyGovernance() view returns (address) +``` + +Returns the address of the emergency governance contract. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyActivationCommittee` + +```solidity +function getEmergencyActivationCommittee() view returns (address) +``` + +Returns the address of the emergency activation committee. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyExecutionCommittee` + +```solidity +function getEmergencyExecutionCommittee() view returns (address) +``` + +Returns the address of the emergency execution committee. + +--- + +### Function: `EmergencyProtectedTimelock.getGovernance` + +```solidity +function getGovernance() view returns (address) +``` + +Returns the address of the current governance contract. + +--- + +### Function: `EmergencyProtectedTimelock.getAdminExecutor` + +```solidity +function getAdminExecutor() view returns (address) +``` + +Returns the address of the admin executor contract. + +--- + +### Function: `EmergencyProtectedTimelock.getAfterSubmitDelay` + +```solidity +function getAfterSubmitDelay() view returns (Duration) +``` + +Returns the configured delay duration required before a submitted proposal can be scheduled. + +--- + +### Function: `EmergencyProtectedTimelock.getAfterScheduleDelay` + +```solidity +function getAfterScheduleDelay() view returns (Duration) +``` + +Returns the configured delay duration required before a scheduled proposal can be executed. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalDetails` + +```solidity +function getProposalDetails(uint256 proposalId) view returns (ProposalDetails memory details) +``` + +Returns information about a proposal, excluding the external calls associated with it. The `ProposalDetails` struct includes the following fields: + +- `id`: The id of the proposal. +- `status`: The current status of the proposal. Possible values are: + - `1`: The proposal was submitted but not scheduled. + - `2`: The proposal was submitted and scheduled but not yet executed. + - `3`: The proposal was submitted, scheduled, and executed. This is the final state of the proposal lifecycle. + - `4`: The proposal was cancelled via `cancelAllNonExecutedProposals` and cannot be scheduled or executed anymore. This is the final state of the proposal lifecycle. +- `executor`: The address of the executor responsible for executing the proposal's external calls. +- `submittedAt`: The timestamp when the proposal was submitted. +- `scheduledAt`: The timestamp when the proposal was scheduled for execution. This value is `0` if the proposal was submitted but not yet scheduled. + +#### Preconditions + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalCalls` -### Function: `Executor.execute` ```solidity -function execute(address target, uint256 value, bytes payload) - payable returns (bytes result) +function getProposalCalls(uint256 proposalId) view returns (ExternalCall[] memory calls) ``` -Issues a external call to the `target` address with the `payload` calldata, optionally sending `value` wei ETH. -Reverts if the call was unsuccessful. +Returns the EVM calls associated with the specified proposal. See the [Struct: ExternalCall](#Struct-ExternalCall) for details on the structure of each call. + +#### Preconditions + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposal` + +```solidity +function getProposal(uint256 proposalId) view returns + (ProposalDetails memory proposalDetails, ExternalCall[] memory calls) +``` + +Retrieves the details of a proposal, including the associated calls to be executed, identified by the proposal's id. + #### Returns -The result of the call. + +- `proposalDetails`: A `ProposalDetails` struct containing metadata and state information about the proposal. +- `calls`: An array of `ExternalCall` structs representing the EVM calls associated with the proposal. + #### Preconditions -* MUST be called by the contract owner (which SHOULD be the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance). + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalsCount` + +```solidity +function getProposalsCount() view returns (uint256 count) +``` + +Returns the total number of proposals submitted to the system. + +--- + +### Function: `EmergencyProtectedTimelock.canExecute` + +```solidity +function canExecute(uint256 proposalId) view returns (bool) +``` + +Checks whether the specified proposal can be executed. + +--- + +### Function: `EmergencyProtectedTimelock.canSchedule` + +```solidity +function canSchedule(uint256 proposalId) view returns (bool) +``` + +Checks whether the specified proposal can be scheduled. + +--- + +### Function: `EmergencyProtectedTimelock.setAdminExecutor` + +```solidity +function setAdminExecutor(address newAdminExecutor) +``` + +Sets a new address for the admin executor contract. + +#### Preconditions + +- MUST be called by the current admin executor contract. +- The `newAdminExecutor` address MUST NOT be the zero address. +- The `newAdminExecutor` address MUST NOT be the same as the current value. + +--- + +## Contract: `Executor` + +Handles calls resulting from governance proposals' execution. Every protocol permission or role protected by the TG, as well as the permission to manage these roles or permissions, must be controlled exclusively by instances of this contract. + +The timelocked governance setup is designed to use a single admin instance of the `Executor`, which is owned by the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance. + +--- + +### Function: `Executor.execute` + +```solidity +function execute(address target, uint256 value, bytes payload) payable +``` + +Performs an EVM call to the `target` address with the specified `payload` calldata, optionally transferring `value` wei in ETH. + +Reverts if the call fails. + +--- \ No newline at end of file diff --git a/docs/specification.md b/docs/specification.md index cac5f864..610ecc38 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -1,7 +1,3 @@ -**Working draft** - ---- - # Dual Governance specification Dual Governance (DG) is a governance subsystem that sits between the Lido DAO, represented by various voting systems, and the protocol contracts it manages. It protects protocol users from hostile actions by the DAO by allowing to cooperate and block any in-scope governance decision until either the DAO cancels this decision or users' (w)stETH is completely withdrawn to ETH. @@ -9,35 +5,34 @@ Dual Governance (DG) is a governance subsystem that sits between the Lido DAO, r This document provides the system description on the code architecture level. A detailed description on the mechanism level can be found in the [Dual Governance mechanism design overview][mech design] document which should be considered an integral part of this specification. [mech design]: mechanism.md - [mech design - tiebreaker]: mechanism.md#Tiebreaker-Committee ## Navigation -* [System overview](#system-overview) -* [Proposal flow](#proposal-flow) - + [Dynamic timelock](#dynamic-timelock) - + [Proposal execution and deployment modes](#proposal-execution-and-deployment-modes) -* [Governance state](#governance-state) -* [Rage quit](#rage-quit) -* [Tiebreaker committee](#tiebreaker-committee) -* [Administrative actions](#administrative-actions) -* [Common types](#common-types) -* Core Contracts: - * [Contract: DualGovernance.sol](#contract-dualgovernancesol) - * [Contract: EmergencyProtectedTimelock.sol](#contract-emergencyprotectedtimelocksol) - * [Contract: Executor.sol](#contract-executorsol) - * [Contract: Escrow.sol](#contract-escrowsol) - * [Contract: ImmutableDualGovernanceConfigProvider.sol](#contract-immutabledualgovernanceconfigprovidersol) - * [Contract: ResealManager.sol](#contract-resealmanagersol) -* Committees: - * [Contract: ProposalsList.sol](#contract-proposalslistsol) - * [Contract: HashConsensus.sol](#contract-hashconsensussol) - * [Contract: TiebreakerCoreCommittee.sol](#contract-tiebreakercorecommitteesol) - * [Contract: TiebreakerSubCommittee.sol](#contract-tiebreakersubcommitteesol) -* [Upgrade flow description](#upgrade-flow-description) - +- [System overview](#system-overview) +- [Proposal flow](#proposal-flow) + - [Dynamic timelock](#dynamic-timelock) + - [Proposal execution and deployment modes](#proposal-execution-and-deployment-modes) +- [Governance state](#governance-state) +- [Rage quit](#rage-quit) +- [Tiebreaker committee](#tiebreaker-committee) +- [Administrative actions](#administrative-actions) +- [Common types](#common-types) +- Core Contracts: + - [Contract: `DualGovernance`](#contract-dualgovernance) + - [Contract: `EmergencyProtectedTimelock`](#contract-emergencyprotectedtimelock) + - [Contract: `Executor`](#contract-executor) + - [Contract: `Escrow`](#contract-escrow) + - [Contract: `ImmutableDualGovernanceConfigProvider`](#contract-immutabledualgovernanceconfigprovider) + - [Contract: ResealManager](#contract-resealmanager) +- Committees: + - [Contract: `ProposalsList`](#contract-proposalslist) + - [Contract: `HashConsensus`](#contract-hashconsensus) + - [Contract: `TiebreakerCoreCommittee`](#contract-tiebreakercorecommittee) + - [Contract: `TiebreakerSubCommittee`](#contract-tiebreakersubcommittee) +- [Upgrade flow description](#upgrade-flow-description) +- [Known risks and limitations](#known-risks-and-limitations) ## System overview @@ -46,17 +41,19 @@ This document provides the system description on the code architecture level. A The system is composed of the following main contracts: -* [`DualGovernance.sol`](#contract-dualgovernancesol) is a singleton that provides an interface for submitting governance proposals and scheduling their execution, as well as managing the list of supported proposers (DAO voting systems). Implements a state machine tracking the current global governance state which, in turn, determines whether proposal submission and execution is currently allowed. -* [`EmergencyProtectedTimelock.sol`](#contract-emergencyprotectedtimelocksol) is a singleton that stores submitted proposals and provides an interface for their execution. In addition, it implements an optional temporary protection from a zero-day vulnerability in the dual governance contracts following the initial deployment or upgrade of the system. The protection is implemented as a timelock on proposal execution combined with two emergency committees that have the right to cooperate and disable the dual governance. -* [`Executor.sol`](#contract-executorsol) contract instances make calls resulting from governance proposals' execution. Every protocol permission or role protected by the DG, as well as the permission to manage this role/permission, should be assigned exclusively to one of the instances of this contract (in contrast with being assigned directly to a DAO voting system). -* [`Escrow.sol`](#contract-escrowsol) is a contract that can hold stETH, wstETH, withdrawal NFTs, and plain ETH. It can exist in two states, each serving a different purpose: either an oracle for users' opposition to DAO proposals or an immutable and ungoverned accumulator for the ETH withdrawn as a result of the [rage quit](#rage-quit). -* [`ImmutableDualGovernanceConfigProvider.sol`](#contract-immutabledualgovernanceconfigprovidersol) is a singleton contract that stores the configurable parameters of the DualGovernance system in an immutable manner. -* [`ResealManager.sol`](#contract-resealmanagersol) is a singleton contract responsible for extending or resuming sealable contracts paused by the [GateSeal emergency protection mechanism](https://github.com/lidofinance/gate-seals). This contract is essential due to the dynamic timelock of Dual Governance, which may prevent the DAO from extending the pause in time. It holds the authority to manage the pausing and resuming of specific protocol components protected by GateSeal. +- [`DualGovernance`](#contract-dualgovernance) is a singleton that provides an interface for submitting governance proposals and scheduling their execution, as well as managing the list of supported proposers (DAO voting systems). Implements a state machine tracking the current global governance state which, in turn, determines whether proposal submission and execution is currently allowed. +- [`EmergencyProtectedTimelock`](#contract-emergencyprotectedtimelock) is a singleton that stores submitted proposals and provides an interface for their execution. In addition, it implements an optional temporary protection from a zero-day vulnerability in the Dual Governance contracts following the initial deployment or upgrade of the system. The protection is implemented as a timelock on proposal execution combined with two emergency committees that have the right to cooperate and disable the Dual Governance. +- [`Executor`](#contract-executor) contract instances make calls resulting from governance proposals' execution. Each `Executor` instance is owned by the `EmergencyProtectedTimelock` singleton. All protocol permissions or roles protected by the Dual Governance must be exclusively controlled by one of the `Executor` instance, rather than being assigned directly to a DAO voting system. A specific `Executor` instance is designated as the admin executor, with the authority to manage the Dual Governance system. +- [`Escrow`](#contract-escrow) is a contract that can hold stETH, wstETH, withdrawal NFTs, and plain ETH. It can exist in two states, each serving a different purpose: either an oracle for users' opposition to DAO proposals or an immutable and ungoverned accumulator for the ETH withdrawn as a result of the [rage quit](#rage-quit). +- [`ImmutableDualGovernanceConfigProvider`](#contract-immutabledualgovernanceconfigprovider) is a singleton contract that stores the configurable parameters of the Dual Governance in an immutable manner. +- [`ResealManager`](#contract-resealmanager) is a singleton contract responsible for extending or resuming sealable contracts paused by the [GateSeal emergency protection mechanism](https://github.com/lidofinance/gate-seals). This contract is essential due to the dynamic timelock of the Dual Governance, which may prevent the DAO from extending the pause in time. It holds the authority to manage the pausing and resuming of specific protocol components protected by GateSeal. + +Additionally, the system incorporates several committee contracts that enable members to achieve quorum and execute a limited set of actions, while ensuring that the management of these committees is safeguarded by the Dual Governance mechanism. Additionally, the system uses several committee contracts that allow members to execute, acquiring quorum, a narrow set of actions while protecting management of the committees by the Dual Governance mechanism: -* [`TiebreakerCoreCommittee.sol`](#contract-tiebreakercorecommitteesol) is a committee contract designed to approve proposals for execution in extreme situations where the Dual Governance system is deadlocked. This includes scenarios such as the inability to finalize user withdrawal requests during ongoing `RageQuit` or when the system is held in a locked state for an extended period. The `TiebreakerCoreCommittee` consists of multiple `TiebreakerSubCommittee` contracts appointed by the DAO. -* [`TiebreakerSubCommittee.sol`](#contract-tiebreakersubcommitteesol) is a committee contracts that provides ability to participate in `TiebreakerCoreCommittee` for external actors. +- [`TiebreakerCoreCommittee`](#contract-tiebreakercorecommittee) is a committee contract designed to approve proposals for execution in extreme situations where the Dual Governance is deadlocked. This includes scenarios such as the inability to finalize user withdrawal requests during ongoing `RageQuit` or when the system is held in a locked state for an extended period. The `TiebreakerCoreCommittee` consists of multiple `TiebreakerSubCommittee` contracts appointed by the DAO. +- [`TiebreakerSubCommittee`](#contract-tiebreakersubcommittee) is a committee contracts that provides ability to participate in `TiebreakerCoreCommittee` for external actors. ## Proposal flow @@ -67,7 +64,7 @@ The system supports multiple DAO voting systems, represented in the dual governa The general proposal flow is the following: -1. A proposer submits a proposal, i.e. a set of EVM calls (represented by an array of [`ExternalCall`](#Struct-ExternalCall) structs) to be issued by the proposer's associated [executor contract](#Contract-Executorsol), by calling the [`DualGovernance.submitProposal`](#Function-DualGovernancesubmitProposal) function. +1. A proposer submits a proposal, i.e. a set of EVM calls (represented by an array of [`ExternalCall`](#Struct-ExternalCall) structs) to be issued by the proposer's associated [executor contract](#Contract-Executor), by calling the [`DualGovernance.submitProposal`](#Function-DualGovernancesubmitProposal) function. 2. This starts a [dynamic timelock period](#Dynamic-timelock) that allows stakers to oppose the DAO, potentially leaving the protocol before the timelock elapses. 3. By the end of the dynamic timelock period, the proposal is either canceled by the DAO or executable. * If it's canceled, it cannot be scheduled for execution. However, any proposer is free to submit a new proposal with the same set of calls. @@ -79,18 +76,18 @@ The general proposal flow is the following: Each submitted proposal requires a minimum timelock before it can be scheduled for execution. -At any time, including while a proposal's timelock is lasting, stakers can signal their opposition to the DAO by locking their (w)stETH or stETH withdrawal NFTs (unstETH) into the [signalling escrow contract](#Contract-Escrowsol). If the opposition exceeds some minimum threshold, the [global governance state](#Governance-state) gets changed, blocking any DAO execution and thus effectively extending the timelock of all pending (i.e. submitted but not scheduled for execution) proposals. +At any time, including while a proposal's timelock is lasting, stakers can signal their opposition to the DAO by locking their (w)stETH or stETH withdrawal NFTs (unstETH) into the [signalling escrow contract](#Contract-Escrow). If the opposition reaches some minimum threshold, the [global governance state](#Governance-state) gets changed, blocking any DAO execution and thus effectively extending the timelock of all pending (i.e. submitted but not scheduled for execution) proposals. ![image](https://github.com/lidofinance/dual-governance/assets/1699593/98273df0-f3fd-4149-929d-3315a8e81aa8) -At any time, the DAO can cancel all pending proposals by calling the [`DualGovernance.cancelAllPendingProposals`](#Function-DualGovernancecancelAllPendingProposals) function. +While the Dual Governance is in the `VetoSignalling` or `VetoSignallingDeactivation` states, the DAO has the ability to cancel all pending proposals by invoking the [`DualGovernance.cancelAllPendingProposals`](#Function-DualGovernancecancelAllPendingProposals) function. By the time the dynamic timelock described above elapses, one of the following outcomes is possible: -* The DAO was not opposed by stakers (the **happy path** scenario). -* The DAO was opposed by stakers and canceled all pending proposals (the **two-sided de-escalation** scenario). -* The DAO was opposed by stakers and didn't cancel pending proposals, forcing the stakers to leave via the rage quit process, or canceled the proposals but some stakers still left (the **rage quit** scenario). -* The DAO was opposed by stakers and didn't cancel pending proposals but the total stake opposing the DAO was too small to trigger the rage quit (the **failed escalation** scenario). +- The DAO was not opposed by stakers (the **happy path** scenario). +- The DAO was opposed by stakers and canceled all pending proposals (the **two-sided de-escalation** scenario). +- The DAO was opposed by stakers and didn't cancel pending proposals, forcing the stakers to leave via the rage quit process, or canceled the proposals but some stakers still left (the **rage quit** scenario). +- The DAO was opposed by stakers and didn't cancel pending proposals but the total stake opposing the DAO was too small to trigger the rage quit (the **failed escalation** scenario). ### Proposal execution and deployment modes @@ -128,25 +125,25 @@ The DG system implements a state machine tracking the **global governance state* The state machine is specified in the [Dual Governance mechanism design][mech design] document. The possible states are: -* `Normal` allows proposal submission and scheduling for execution. -* `VetoSignalling` only allows proposal submission. - * `VetoSignallingDeactivation` sub-state (doesn't deactivate the parent state upon entry) doesn't allow proposal submission or scheduling for execution. -* `VetoCooldown` only allows scheduling already submitted proposals for execution. -* `RageQuit` only allows proposal submission. +- `Normal` allows proposal submission and scheduling for execution. +- `VetoSignalling` only allows proposal submission. + - `VetoSignallingDeactivation` sub-state (doesn't deactivate the parent state upon entry) doesn't allow proposal submission or scheduling for execution. +- `VetoCooldown` only allows scheduling already submitted proposals for execution. +- `RageQuit` only allows proposal submission. ![image](https://github.com/lidofinance/dual-governance/assets/1699593/44c2b253-6ea2-4aac-a1c6-fd54cec92887) Possible state transitions: -* `Normal` → `VetoSignalling` -* `VetoSignalling` → `RageQuit` -* `VetoSignallingDeactivation` sub-state entry and exit (while the parent `VetoSignalling` state is active) -* `VetoSignallingDeactivation` → `RageQuit` -* `VetoSignallingDeactivation` → `VetoCooldown` -* `VetoCooldown` → `Normal` -* `VetoCooldown` → `VetoSignalling` -* `RageQuit` → `VetoCooldown` -* `RageQuit` → `VetoSignalling` +- `Normal` → `VetoSignalling` +- `VetoSignalling` → `RageQuit` +- `VetoSignalling` → `VetoSignallingDeactivation` - sub-state entry and exit (while the parent `VetoSignalling` state is active) +- `VetoSignallingDeactivation` → `RageQuit` +- `VetoSignallingDeactivation` → `VetoCooldown` +- `VetoCooldown` → `Normal` +- `VetoCooldown` → `VetoSignalling` +- `RageQuit` → `VetoCooldown` +- `RageQuit` → `VetoSignalling` These transitions are enabled by three processes (see the [mechanism design document][mech design] for more details): @@ -182,18 +179,18 @@ The Tiebreaker committee is represented in the system by its address which can b While the deadlock conditions are met, the Tiebreaker committee address is allowed to: -1. Schedule execution of any pending proposal by calling [`DualGovernance.tiebreakerScheduleProposal`] after the tiebreaker execution timelock passes. -2. Unpause of a pausable ("sealable") protocol contract by calling [`DualGovernance.tiebreakerResumeSealable`] after the tiebreaker execution timelock passes. +1. Schedule execution of any pending proposal by calling [`DualGovernance.tiebreakerScheduleProposal`] after the tiebreaker activation timeout passes. +2. Unpause of a pausable ("sealable") protocol contract by calling [`DualGovernance.tiebreakerResumeSealable`] after the tiebreaker activation timeout passes. ## Administrative actions The dual governance system supports a set of administrative actions, including: -* Changing the configuration options. -* [Upgrading the system's code](#Upgrade-flow-description). -* Managing the [deployment mode](#Proposal-execution-and-deployment-modes): configuring or disabling the emergency protection delay, setting the emergency committee addresses and lifetime. -* Setting the [Tiebreaker committee](#Tiebreaker-committee) address. +- Changing the configuration options. +- [Upgrading the system's code](#Upgrade-flow-description). +- Managing the [deployment mode](#Proposal-execution-and-deployment-modes): configuring or disabling the emergency protection delay, setting the emergency committee addresses and lifetime. +- Setting the [Tiebreaker committee](#Tiebreaker-committee) address. Each of these actions can only be performed by a designated **admin executor** contract (declared in the `EmergencyProtectedTimelock` instance), meaning that: @@ -203,7 +200,7 @@ Each of these actions can only be performed by a designated **admin executor** c ## Common types -### Struct: ExternalCall +### Struct: `ExternalCall` ```solidity struct ExternalCall { @@ -215,20 +212,21 @@ struct ExternalCall { Encodes an EVM call from an executor contract to the `target` address with the specified `value` and the calldata being set to `payload`. +--- -## Contract: DualGovernance.sol +## Contract: `DualGovernance` The main entry point to the dual governance system. -* Provides an interface for submitting and cancelling governance proposals and implements a dynamic timelock on scheduling their execution. -* Manages the list of supported proposers (DAO voting systems). -* Implements a state machine tracking the current [global governance state](#Governance-state) which, in turn, determines whether proposal submission and execution is currently allowed. -* Deploys and tracks the [`Escrow`](#Contract-Escrowsol) contract instances. Tracks the current signalling escrow. +- Provides an interface for submitting and cancelling governance proposals and implements a dynamic timelock on scheduling their execution. +- Manages the list of supported proposers (DAO voting systems). +- Implements a state machine tracking the current [global governance state](#Governance-state) which, in turn, determines whether proposal submission and execution is currently allowed. +- Deploys and tracks the [`Escrow`](#Contract-Escrow) contract instances. Tracks the current signalling escrow. This contract is a singleton, meaning that any DG deployment includes exactly one instance of this contract. -### Enum: DualGovernanceStateMachine.State +### Enum: `DualGovernanceStateMachine.State` ```solidity enum State { @@ -243,35 +241,34 @@ enum State { Encodes the current global [governance state](#Governance-state), affecting the set of actions allowed for each of the system's actors. +--- -### Function: DualGovernance.submitProposal +### Function: `DualGovernance.submitProposal` ```solidity -function submitProposal(ExecutorCall[] calls, string calldata metadata) +function submitProposal(ExternalCall[] calls, string calldata metadata) returns (uint256 proposalId) ``` -Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance to register a new governance proposal composed of one or more EVM `calls`, along with the attached `metadata` text. The proposal will be executed by an executor contract currently associated with the proposer address calling this function. Starts a dynamic timelock on [scheduling the proposal](#Function-DualGovernancescheduleProposal) for execution. +Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance to register a new governance proposal composed of one or more EVM `calls`, along with the attached `metadata` text. The proposal will be executed by an executor contract associated with the proposer address calling this function at the moment of submission. Starts a dynamic timelock on [scheduling the proposal](#Function-DualGovernancescheduleProposal) for execution. See: [`EmergencyProtectedTimelock.submit`](#Function-EmergencyProtectedTimelocksubmit). -#### Returns - -The id of the successfully registered proposal. +Returns the id of the successfully registered proposal. #### Preconditions -* The calling address MUST be [registered as a proposer](#Function-DualGovernanceregisterProposer). -* The current governance state MUST be either of: `Normal`, `VetoSignalling`, `RageQuit`. +- The calling address MUST be [registered as a proposer](#Function-DualGovernanceregisterProposer). +- The current governance state MUST be either of: `Normal`, `VetoSignalling`, `RageQuit`. Triggers a transition of the current governance state (if one is possible) before checking the preconditions. -### Function: DualGovernance.scheduleProposal +--- -[`DualGovernance.scheduleProposal`]: #Function-DualGovernancescheduleProposal +### Function: `DualGovernance.scheduleProposal` ```solidity -function scheduleProposal(uint256 proposalId) external +function scheduleProposal(uint256 proposalId) ``` Schedules a previously submitted proposal for execution in the Dual Governance system. The function ensures that the proposal meets specific conditions before it can be scheduled. If the conditions are met, the proposal is registered for execution in the `EmergencyProtectedTimelock` singleton instance. @@ -279,15 +276,17 @@ Schedules a previously submitted proposal for execution in the Dual Governance s Preconditions - The proposal with the specified proposalId MUST exist in the system. -- The required delay since submission (`EmergencyProtectedTimelock.getAfterSubmitDelay()`) MUST have elapsed. -- The Dual Governance system MUST BE in the `Normal` or `VetoCooldown` state +- The required delay since submission (`EmergencyProtectedTimelock.getAfterSubmitDelay`) MUST have elapsed. +- The Dual Governance system MUST be in the `Normal` or `VetoCooldown` state - If the system is in the `VetoCooldown` state, the proposal MUST have been submitted not later than the `VetoSignalling` state was entered. - The proposal MUST NOT have been cancelled. - The proposal MUST NOT already be scheduled. Triggers a transition of the current governance state (if one is possible) before checking the preconditions. -### Function: DualGovernance.cancelAllPendingProposals +--- + +### Function: `DualGovernance.cancelAllPendingProposals` ```solidity function cancelAllPendingProposals() returns (bool) @@ -295,15 +294,18 @@ function cancelAllPendingProposals() returns (bool) Cancels all currently submitted and non-executed proposals. If a proposal was submitted but not scheduled, it becomes unschedulable. If a proposal was scheduled, it becomes unexecutable. -If the current governance state is neither `VetoSignalling` nor `VetoSignallingDeactivation`, the function will exit early without canceling any proposals, emitting the `CancelAllPendingProposalsSkipped` event and returning `false`. If proposals are successfully canceled, the `CancelAllPendingProposalsExecuted` event will be emitted, and the function will return `true`. +If the current governance state is neither `VetoSignalling` nor `VetoSignallingDeactivation`, the function will exit early without canceling any proposals, emitting the `CancelAllPendingProposalsSkipped` event and returning `false`. +If proposals are successfully canceled, the `CancelAllPendingProposalsExecuted` event will be emitted, and the function will return `true`. #### Preconditions -- MUST be called by an authorized `proposalsCanceller` +- MUST be called by an authorized `proposalsCanceller`. Triggers a transition of the current governance state, if one is possible. -### Function: DualGovernance.activateNextState +--- + +### Function: `DualGovernance.activateNextState` ```solidity function activateNextState() @@ -311,8 +313,86 @@ function activateNextState() Triggers a transition of the [global governance state](#Governance-state), if one is possible; does nothing otherwise. +--- + +### Function: `DualGovernance.setConfigProvider` + +```solidity +function setConfigProvider(IDualGovernanceConfigProvider newConfigProvider) +``` + +Sets the configuration provider for the Dual Governance system. + +#### Preconditions +- MUST be called by the admin executor. +- The `newConfigProvider` address MUST NOT be the zero address. +- The `newConfigProvider` address MUST NOT be the same as the current configuration provider. +- The values returned by the config MUST be valid: + - `firstSealRageQuitSupport` MUST be less than `secondSealRageQuitSupport`. + - `vetoSignallingMinDuration` MUST be less than `vetoSignallingMaxDuration`. + - `rageQuitEthWithdrawalsMinDelay` MUST be less than or equal to `rageQuitEthWithdrawalsMaxDelay`. + - `minAssetsLockDuration` MUST NOT be zero. + - `minAssetsLockDuration` MUST NOT exceed `Escrow.MAX_MIN_ASSETS_LOCK_DURATION`. + +--- + +### Function: `DualGovernance.setProposalsCanceller` + +```solidity +function setProposalsCanceller(address newProposalsCanceller) +``` + +Updates the address of the proposals canceller authorized to cancel pending proposals. Typically, this should be set to one of the DAO voting systems but can also be assigned to a contract with additional logic. + +#### Preconditions +- MUST be called by the admin executor. +- The `newProposalsCanceller` address MUST NOT be the zero address. +- The `newProposalsCanceller` address MUST NOT be the same as the current proposals canceller. + +--- + +### Function: `DualGovernance.getProposalsCanceller` + +```solidity +function getProposalsCanceller() view returns (address) +``` + +Returns the address of the current proposals canceller. + +--- + +### Function: `DualGovernance.getConfigProvider` + +```solidity +function getConfigProvider() view returns (IDualGovernanceConfigProvider) +``` + +Returns the current configuration provider for the Dual Governance system. + +--- + +### Function: `DualGovernance.getVetoSignallingEscrow` + +```solidity +function getVetoSignallingEscrow() view returns (address) +``` + +Returns the address of the veto signaling escrow contract. + +--- + +### Function: `DualGovernance.getRageQuitEscrow` + +```solidity +function getRageQuitEscrow() view returns (address) +``` + +Returns the address of the rage quit escrow contract associated with the most recent or ongoing rage quit. +If no rage quits have occurred in the system, the returned address will be the zero address. + +--- -### Function: DualGovernance.getPersistedState +### Function: `DualGovernance.getPersistedState` ```solidity function getPersistedState() view returns (State persistedState) @@ -320,15 +400,19 @@ function getPersistedState() view returns (State persistedState) Returns the most recently persisted state of the DualGovernance. -### Function: DualGovernance.getEffectiveState +--- + +### Function: `DualGovernance.getEffectiveState` ```solidity function getEffectiveState() view returns (State persistedState) ``` -Returns the effective state of the DualGovernance. The effective state refers to the state the DualGovernance would transition to upon calling `DualGovernance.activateNextState()`. +Returns the effective state of the DualGovernance. The effective state refers to the state the DualGovernance would transition to upon calling `DualGovernance.activateNextState`. + +--- -### Function DualGovernance.getStateDetails +### Function `DualGovernance.getStateDetails` ```solidity function getStateDetails() view returns (StateDetails) @@ -336,7 +420,7 @@ function getStateDetails() view returns (StateDetails) This function returns detailed information about the current state of the `DualGovernance`, comprising the following data: -- **`State effectiveState`**: The state that the `DualGovernance` would transition to upon calling `DualGovernance.activateNextState()`. +- **`State effectiveState`**: The state that the `DualGovernance` would transition to upon calling `DualGovernance.activateNextState`. - **`State persistedState`**: The current stored state of the `DualGovernance`. - **`Timestamp persistedStateEnteredAt`**: The timestamp when the `persistedState` was entered. - **`Timestamp vetoSignallingActivatedAt`**: The timestamp when the `VetoSignalling` state was last activated. @@ -345,38 +429,192 @@ This function returns detailed information about the current state of the `DualG - **`uint256 rageQuitRound`**: The number of continuous RageQuit rounds. - **`Duration vetoSignallingDuration`**: The duration of the `VetoSignalling` state, calculated based on the RageQuit support in the Veto Signalling `Escrow`. +--- + +### Function: `DualGovernance.registerProposer` + +```solidity +function registerProposer(address proposerAccount, address executor) +``` + +Registers the `proposerAccount` address in the system as a valid proposer and associates it with the `executor` contract address. The `executor` is expected to be an instance of [`Executor`](#Contract-Executor). + +#### Preconditions + +- MUST be called by the admin executor. +- The `proposerAccount` address MUST NOT be the zero address. +- The `executor` address MUST NOT be the zero address. +- The `proposerAccount` address MUST NOT already be registered in the system. + +--- + +### Function: `DualGovernance.setProposerExecutor` + +```solidity +function setProposerExecutor(address proposerAccount, address newExecutor) +``` + +Updates the executor associated with a specified proposer. The `newExecutor` is expected to be an instance of [`Executor`](#Contract-Executor). + +#### Preconditions + +- MUST be called by the admin executor. +- The `proposerAccount` address MUST be registered in the system. +- The `newExecutor` address MUST NOT be the zero address. +- The `newExecutor` address MUST NOT be the same as the current executor associated with the `proposerAccount`. +- Updating the proposer’s executor MUST NOT result in the admin executor having no associated proposer. + +--- + +### Function: `DualGovernance.unregisterProposer` + +```solidity +function unregisterProposer(address proposerAccount) +``` + +Removes the registered `proposerAccount` address from the list of valid proposers and dissociates it with the executor contract address. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `proposerAccount` address MUST be registered in the system as proposer. +- The `proposerAccount` address MUST NOT be the only one assigned to the admin executor. + +--- + +### Function: `DualGovernance.getProposer` + +```solidity +function getProposer(address proposerAccount) view returns (Proposers.Proposer memory proposer) +``` + +Returns the proposer data for the specified `proposerAccount` if it is a registered proposer. The returned data includes: +- **`account`**: The address of the registered proposer. +- **`executor`**: The address of the executor associated with the proposer. + +#### Preconditions +- The `proposerAccount` MUST be registered in the system as a proposer. + +--- + +### Function: `DualGovernance.getProposers` + +```solidity +function getProposers() view returns (Proposers.Proposer[] memory proposers) +``` + +Returns information about all registered proposers. Each item in the returned array includes the following fields: +- **`account`**: The address of the registered proposer. +- **`executor`**: The address of the executor associated with the proposer. + +--- + +### Function: `DualGovernance.isProposer` + +```solidity +function isProposer(address proposerAccount) view returns (bool) +``` + +Returns whether the specified `proposerAccount` is a registered proposer. + +--- + +### Function: `DualGovernance.isExecutor` + +```solidity +function isExecutor(address executor) view returns (bool) +``` + +Returns whether the specified `executor` address is assigned as the executor for at least one registered proposer. + +--- + +### Function: `DualGovernance.addTiebreakerSealableWithdrawalBlocker` + +```solidity +function addTiebreakerSealableWithdrawalBlocker(address sealableWithdrawalBlocker) +``` + +Adds a unique address of a sealable contract that can be paused and may cause a Dual Governance tie (deadlock). A tie may occur when user withdrawal requests cannot be processed due to the paused state of a registered sealable withdrawal blocker while the Dual Governance system is in the RageQuit state. + +#### Preconditions + +- MUST be called by the admin executor. +- The `sealableWithdrawalBlocker` address MUST implement the `ISealable` interface. +- The total number of registered sealable withdrawal blockers MUST NOT equal `DualGovernance.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT`. +- The `sealableWithdrawalBlocker` address MUST NOT be in a paused state at the time of addition. +- The `sealableWithdrawalBlocker` address MUST NOT already be registered. + +--- + +### Function: `DualGovernance.removeTiebreakerSealableWithdrawalBlocker` + +```solidity +function removeTiebreakerSealableWithdrawalBlocker(address sealableWithdrawalBlocker) +``` + +Removes a previously registered `sealableWithdrawalBlocker` contract from the system. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `sealableWithdrawalBlocker` address MUST have been previously registered using the `DualGovernance.addTiebreakerSealableWithdrawalBlocker` method. + +--- + +### Function: `DualGovernance.setTiebreakerCommittee` + +```solidity +function setTiebreakerCommittee(address newTiebreaker) +``` + +Updates the address of the [Tiebreaker committee](#Tiebreaker-committee). + +#### Preconditions + +- MUST be called by the admin executor. +- The `newTiebreaker` address MUST NOT be the zero address. +- The `newTiebreaker` address MUST be different from the current tiebreaker address. + +--- -### Function: DualGovernance.registerProposer +### Function: `DualGovernance.setTiebreakerActivationTimeout` ```solidity -function registerProposer(address proposer, address executor) +function setTiebreakerActivationTimeout(Duration newTiebreakerActivationTimeout) ``` -Registers the `proposer` address in the system as a valid proposer and associates it with the `executor` contract address (which is expected to be an instance of [`Executor.sol`](#Contract-Executorsol)) as an executor. +Sets a new value for the tiebreaker activation timeout. If the Dual Governance system remains out of the `Normal` or `VetoCooldown` state for longer than the `tiebreakerActivationTimeout` duration, the tiebreaker committee is permitted to schedule submitted proposals. #### Preconditions -* MUST be called by the admin executor contract. -* The `proposer` address MUST NOT be already registered in the system. -* The `executor` instance SHOULD be owned by the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance. +- MUST be called by the admin executor contract. +- The `newTiebreakerActivationTimeout` MUST be greater than or equal to `DualGovernance.MIN_TIEBREAKER_ACTIVATION_TIMEOUT`. +- The `newTiebreakerActivationTimeout` MUST be less than or equal to `DualGovernance.MAX_TIEBREAKER_ACTIVATION_TIMEOUT`. +- The `newTiebreakerActivationTimeout` MUST be different from the current value. + +--- +### Function: `DualGovernance.tiebreakerResumeSealable` -### Function: DualGovernance.unregisterProposer +[`DualGovernance.tiebreakerResumeSealable`]: #Function-DualGovernancetiebreakerResumeSealable ```solidity -function unregisterProposer(address proposer) +function tiebreakerResumeSealable(address sealable) ``` -Removes the registered `proposer` address from the list of valid proposers and dissociates it with the executor contract address. +Allows the [Tiebreaker committee](#Tiebreaker-committee) to resume a paused sealable contract when the system is in a tie state. #### Preconditions -* MUST be called by the admin executor contract. -* The `proposer` address MUST be registered in the system as proposer. -* The `proposer` address MUST NOT be the only one assigned to the admin executor. +- MUST be called by the [Tiebreaker committee](#Tiebreaker-committee) address. +- Either **Tiebreaker Condition A** or **Tiebreaker Condition B** MUST be met (see the [mechanism design document][mech design - tiebreaker]). + +Triggers a transition of the [global governance state](#Governance-state), if one is possible, before checking the tie state. +--- -### Function: DualGovernance.tiebreakerScheduleProposal +### Function: `DualGovernance.tiebreakerScheduleProposal` [`DualGovernance.tiebreakerScheduleProposal`]: #Function-DualGovernancetiebreakerScheduleProposal @@ -384,139 +622,247 @@ Removes the registered `proposer` address from the list of valid proposers and d function tiebreakerScheduleProposal(uint256 proposalId) ``` -Instructs the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance to schedule the proposal with the id `proposalId` for execution, bypassing the proposal dynamic timelock and given that the proposal was previously approved by the [Tiebreaker committee](#Tiebreaker-committee). +Allows the [Tiebreaker committee](#Tiebreaker-committee) to instruct the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance to schedule a submitted and non-cancelled proposal with the id `proposalId` for execution. This method bypasses the DG's dynamic timelock and can only be called when the system is in a tie state. #### Preconditions -* MUST be called by the [Tiebreaker committee](#Tiebreaker-committee) address -* Either the Tiebreaker Condition A or the Tiebreaker Condition B MUST be met (see the [mechanism design document][mech design - tiebreaker]). -* The proposal with the given id MUST be already submitted using the `DualGovernance.submitProposal` call. -* The proposal MUST NOT be cancelled. +- MUST be called by the [Tiebreaker committee](#Tiebreaker-committee) address. +- Either **Tiebreaker Condition A** or **Tiebreaker Condition B** MUST be met (see the [mechanism design document][mech design - tiebreaker]). +- The proposal with the given id MUST have been previously submitted using the `DualGovernance.submitProposal` call. +- The proposal MUST NOT be cancelled. Triggers a transition of the current governance state (if one is possible) before checking the preconditions. -### Function: DualGovernance.tiebreakerResumeSealable +--- -[`DualGovernance.tiebreakerResumeSealable`]: #Function-DualGovernancetiebreakerResumeSealable +### Function: `DualGovernance.getTiebreakerDetails` ```solidity -function tiebreakerResumeSealable(address sealable) +function getTiebreakerDetails() view returns (ITiebreaker.TiebreakerDetails memory tiebreakerState) +``` + +Returns detailed information about the current tiebreaker state based on the `effective` state of the system. The returned `TiebreakerDetails` struct includes the following data: + +- `isTie`: Indicates whether the system is in a tie state, allowing the [Tiebreaker committee](#Tiebreaker-committee) to schedule proposals or resume sealable contracts. +- `tiebreakerCommittee`: The address of the current [Tiebreaker committee](#Tiebreaker-committee). +- `tiebreakerActivationTimeout`: The duration the system must remain in a "locked" state (not in `Normal` or `VetoCooldown` state) before the [Tiebreaker committee](#Tiebreaker-committee) is permitted to take actions. +- `sealableWithdrawalBlockers`: An array of sealable contracts registered in the system as withdrawal blockers. + +--- + +### Function: `DualGovernance.resealSealable` + +```solidity +function resealSealable(address sealable) ``` -Calls the `ResealManager.resumeSealable(address sealable)` if all preconditions met. +Allows the reseal committee to "reseal" (pause indefinitely) an instance of a sealable contract that is currently paused for a limited duration. This is done using the [`ResealManager`](#Contract-ResealManager) contract. #### Preconditions -* MUST be called by the [Tiebreaker committee](#Tiebreaker-committee) address -* Either the Tiebreaker Condition A or the Tiebreaker Condition B MUST be met (see the [mechanism design document][mech design - tiebreaker]). +- The system MUST NOT be in the `Normal` state. +- The caller MUST be the `resealCommittee` address. +- The `sealable` address MUST implement the `ISealable` interface. +- The `resealManager` MUST have the permissions required to pause and resume the specified `sealable` instance. +- The `sealable`'s `getResumeSinceTimestamp` MUST be a future timestamp and less than `type(uint256).max`. + +Triggers a transition of the current governance state (if one is possible) before checking the preconditions. +--- -### Function: DualGovernance.setTiebreakerCommittee +### Function: `DualGovernance.setResealCommittee` ```solidity -function setTiebreakerCommittee(address newTiebreaker) +function setResealCommittee(address newResealCommittee) ``` -Updates the address of the [Tiebreaker committee](#Tiebreaker-committee). +Sets the address of the reseal committee. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newResealCommittee` address MUST NOT be the same as the current value. + +--- + +### Function: `DualGovernance.setResealManager` + +```solidity +function setResealManager(IResealManager newResealManager) +``` + +Sets the address of the Reseal Manager contract. #### Preconditions -* MUST be called by the admin executor contract. -* The `newTiebreaker` address MUST NOT be the zero address. -* The `newTiebreaker` address MUST be different from the current tiebreaker address. +- MUST be called by the admin executor contract. +- The `newResealManager` address MUST NOT be the same as the current value. +- The `newResealManager` address MUST NOT be the zero address. + +--- + +### Function: `DualGovernance.getResealManager` + +```solidity +function getResealManager() view returns (IResealManager) +``` + +Returns the address of the Reseal Manager contract. +--- + +### Function: `DualGovernance.getResealCommittee` + +```solidity +function getResealCommittee() view returns (address) +``` + +Returns the address of the reseal committee. + +--- -## Contract: Executor.sol +## Contract: `Executor` -Issues calls resulting from governance proposals' execution. Every protocol permission or role protected by the DG, as well as the permission to manage this role/permission, should be assigned exclusively to the instances of this contract. +Handles calls resulting from governance proposals' execution. Every protocol permission or role protected by the Dual Governance system, as well as the permission to manage these roles or permissions, must be controlled exclusively by instances of this contract. -The system supports multiple instances of this contract, but all instances SHOULD be owned by the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance. +The system supports multiple instances of this contract, but all instances SHOULD be owned by the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance. +--- -### Function: execute +### Function: `Executor.execute` ```solidity function execute(address target, uint256 value, bytes payload) payable ``` -Issues a EVM call to the `target` address with the `payload` calldata, optionally sending `value` wei ETH. +Performs an EVM call to the `target` address with the specified `payload` calldata, optionally transferring `value` wei in ETH. -Reverts if the call was unsuccessful. +Reverts if the call fails. #### Preconditions -* MUST be called by the contract owner (which SHOULD be the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelocksol) singleton instance). +- MUST be called by the contract owner (which SHOULD be the [`EmergencyProtectedTimelock`](#Contract-EmergencyProtectedTimelock) singleton instance). + +--- -## Contract: ResealManager.sol +## Contract: `ResealManager` In the Lido protocol, specific critical components (`WithdrawalQueue` and `ValidatorsExitBus`) are safeguarded by the `GateSeal` contract instance. According to the gate seals [documentation](https://github.com/lidofinance/gate-seals?tab=readme-ov-file#what-is-a-gateseal): ->*"A GateSeal is a contract that allows the designated account to instantly put a set of contracts on pause (i.e. seal) for a limited duration. This will give the Lido DAO the time to come up with a solution, hold a vote, implement changes, etc.".* +>*"A GateSeal is a contract that allows the designated account to instantly put a set of contracts on pause (i.e. seal) for a limited duration. This will give the Lido DAO the time to come up with a solution, hold a vote, implement changes, etc."* -However, the effectiveness of this approach is contingent upon the predictability of the DAO's solution adoption timeframe. With the dual governance system, proposal execution may experience significant delays based on the current state of the `DualGovernance` contract. There's a risk that `GateSeal`'s pause period may expire before the Lido DAO can implement the necessary fixes. +However, the effectiveness of this approach depends on the predictability of the DAO's solution adoption timeframe. With the dual governance system, proposal execution may experience significant delays depending on the current state of the `DualGovernance` contract. This creates a risk that the `GateSeal`'s pause period may expire before the Lido DAO can implement the necessary fixes. -The **ResealManager** contract addresses this issue by enabling the extension of temporarily paused contracts into a permanent pause or resuming them if the following conditions are met: +The `ResealManager` contract addresses this issue by enabling the extension of temporarily paused contracts into a permanent pause or by resuming them if the following conditions are met: - The contracts are paused for a limited duration, not indefinitely. -- The **DualGovernance** system is not in the `Normal` state. +- The Dual Governance system is not in the `Normal` state. + +To function properly, the `ResealManager` MUST be granted the `PAUSE_ROLE` and `RESUME_ROLE` for the target contracts. -To function properly, the **ResealManager** must be granted the `PAUSE_ROLE` and `RESUME_ROLE` for the target contracts. +--- -### Function ResealManager.reseal +### Function: `ResealManager.reseal` ```solidity -function reseal(address sealable) external +function reseal(address sealable) ``` Extends the pause of the specified `sealable` contract indefinitely. #### Preconditions -- The `ResealManager` MUST have `PAUSE_ROLE` and `RESUME_ROLE` for the target contract. -- The target contract MUST be paused for a limited duration, with a future timestamp, and not indefinitely. -- The function MUST be called by the governance address defined in `EmergencyProtectedTimelock`. +- The `ResealManager` MUST have both the `PAUSE_ROLE` and `RESUME_ROLE` for the target contract. +- The target contract MUST be paused for a limited duration with a future resume timestamp, and not indefinitely. +- The function MUST be called by the governance address returned by the `EmergencyProtectedTimelock.getGovernance` method. + +--- -### Function: ResealManager.resume +### Function: `ResealManager.resume` ```solidity -function resume(address sealable) external +function resume(address sealable) ``` -Resumes the specified sealable contract if it is scheduled to resume at a future timestamp. +Resumes the specified `sealable` contract if it is scheduled to resume at a future timestamp. #### Preconditions - The `ResealManager` MUST have the `RESUME_ROLE` for the target contract. -- The target contract MUST be paused. -- The function MUST be called by the governance address defined in `EmergencyProtectedTimelock`. +- The target contract MUST currently be paused. +- The function MUST be called by the governance address returned by the `EmergencyProtectedTimelock.getGovernance` method. + +--- -## Contract: Escrow.sol +## Contract: `Escrow` The `Escrow` contract serves as an accumulator of users' (w)stETH, withdrawal NFTs (unstETH), and ETH. It has two internal states and serves a different purpose depending on its state: -* The initial state is the `SignallingEscrow` state. In this state, the contract serves as an oracle for users' opposition to DAO proposals. It allows users to lock and unlock (unlocking is permitted only for the caller after the `MinAssetsLockDuration` has passed since their last funds locking operation) stETH, wstETH, and withdrawal NFTs, potentially changing the global governance state. The `MinAssetsLockDuration` duration, measured in hours, safeguards against manipulating the dual governance state through instant lock/unlock actions within the `Escrow` contract instance. -* The final state is the `RageQuitEscrow` state. In this state, the contract serves as an immutable and ungoverned accumulator for the ETH withdrawn as a result of the [rage quit](#Rage-quit) and enforces a timelock on reclaiming this ETH by users. +- The initial state is the `SignallingEscrow` state. In this state, the contract serves as an oracle for users' opposition to DAO proposals. It allows users to lock and unlock (unlocking is permitted only for the caller after the `minAssetsLockDuration` has passed since their last funds locking operation) stETH, wstETH, and withdrawal NFTs, potentially changing the global governance state. The `minAssetsLockDuration` duration, measured in hours, safeguards against manipulating the dual governance state through instant lock/unlock actions within the `Escrow` contract instance. +- The final state is the `RageQuitEscrow` state. In this state, the contract serves as an immutable and ungoverned accumulator for the ETH withdrawn as a result of the [rage quit](#Rage-quit) and enforces a timelock on reclaiming this ETH by users. -The `DualGovernance` contract tracks the current signalling escrow contract using the `DualGovernance.getVetoSignallingEscrow()` pointer. Upon the initial deployment of the system, an instance of `Escrow` is deployed in the `SignallingEscrow` state by the `DualGovernance` contract, and the `DualGovernance.getVetoSignallingEscrow()` pointer is set to this contract. +The `DualGovernance` contract tracks the current signalling escrow contract using the `DualGovernance.getVetoSignallingEscrow` pointer. Upon the initial deployment of the system, an instance of `Escrow` is deployed in the `SignallingEscrow` state by the `DualGovernance` contract, and the `DualGovernance.getVetoSignallingEscrow` pointer is set to this contract. Each time the governance enters the global `RageQuit` state, two things happen simultaneously: -1. The `Escrow` instance currently stored in the `DualGovernance.getVetoSignallingEscrow()` pointer changes its state from `SignallingEscrow` to `RageQuitEscrow`. This is the only possible (and thus irreversible) state transition. -2. The `DualGovernance` contract deploys a new instance of `Escrow` in the `SignallingEscrow` state and resets the `DualGovernance.getVetoSignallingEscrow()` pointer to this newly-deployed contract. +1. The `Escrow` instance currently stored in the `DualGovernance.getVetoSignallingEscrow` pointer changes its state from `SignallingEscrow` to `RageQuitEscrow`. This is the only possible (and thus irreversible) state transition. +2. The `DualGovernance` contract deploys a new instance of `Escrow` in the `SignallingEscrow` state and resets the `DualGovernance.getVetoSignallingEscrow` pointer to this newly-deployed contract. At any point in time, there can be only one instance of the contract in the `SignallingEscrow` state (so the contract in this state is a singleton) but multiple instances of the contract in the `RageQuitEscrow` state. -After the `Escrow` instance transitions into the `RageQuitEscrow` state, all locked stETH and wstETH tokens are meant to be converted into withdrawal NFTs using the permissionless `Escrow.requestNextWithdrawalsBatch()` function. +After the `Escrow` instance transitions into the `RageQuitEscrow` state, all locked stETH and wstETH tokens are meant to be converted into withdrawal NFTs using the permissionless `Escrow.requestNextWithdrawalsBatch` function. -Once all funds locked in the `Escrow` instance are converted into withdrawal NFTs, finalized, and claimed, the main rage quit phase concludes, and the `Escrow.startRageQuitExtensionPeriod()` method may be used to start the `RageQuitExtensionPeriod`. +Once all funds locked in the `Escrow` instance are converted into withdrawal NFTs, finalized, and claimed, the main rage quit phase concludes, and the `Escrow.startRageQuitExtensionPeriod` method may be used to start the `RageQuitExtensionPeriod`. -The purpose of the `startRageQuitExtensionPeriod` is to provide participants who have locked withdrawal NFTs (unstETH) with additional time to [claim](https://docs.lido.fi/contracts/withdrawal-queue-erc721#claim) them before the Lido DAO’s proposal execution is unblocked. During the entire RageQuit period (including the RageQuitExtensionPeriod), users are able to claim their locked unstETH, ensuring that the DAO cannot affect the ETH tied to their Withdrawal NFT. It is expected that users will claim their unstETH within this time frame to safeguard their ETH. While users can still claim their ETH after the `RageQuitExtensionPeriod`, **they risk losing all ETH associated with their locked unstETH**, as a malicious DAO could still exert control over the WithdrawalQueue contract. +The purpose of the `startRageQuitExtensionPeriod` is to provide participants who have locked withdrawal NFTs (unstETH) with additional time to [claim](https://docs.lido.fi/contracts/withdrawal-queue-erc721#claim) them before the Lido DAO’s proposal execution is unblocked. During the entire `RageQuit` period (including the `RageQuitExtensionPeriod`), users are able to claim their locked unstETH, ensuring that the DAO cannot affect the ETH tied to their Withdrawal NFT. It is expected that users will claim their unstETH within this time frame to safeguard their ETH. While users can still claim their ETH after the `RageQuitExtensionPeriod`, **they risk losing all ETH associated with their locked unstETH**, as a malicious DAO could still exert control over the `WithdrawalQueue` contract. -When the `startRageQuitExtensionPeriod` period elapses, the `DualGovernance.activateNextState()` function exits the `RageQuit` state and initiates the `RageQuitEthWithdrawalsDelay`. Throughout this timelock, tokens remain locked within the `Escrow` instance and are inaccessible for withdrawal. Once the timelock expires, participants in the rage quit process can retrieve their ETH by withdrawing it from the `Escrow` instance. +When the `startRageQuitExtensionPeriod` period elapses, the `DualGovernance.activateNextState` function exits the `RageQuit` state and initiates the `RageQuitEthWithdrawalsDelay`. Throughout this timelock, tokens remain locked within the `Escrow` instance and are inaccessible for withdrawal. Once the timelock expires, participants in the rage quit process can retrieve their ETH by withdrawing it from the `Escrow` instance. The duration of the `RageQuitEthWithdrawalsDelay` is dynamic and varies based on the number of "continuous" rage quits. A pair of rage quits is considered continuous when `DualGovernance` has not transitioned to the `Normal` or `VetoCooldown` state between them. -### Function: Escrow.lockStETH +--- + +### Enum: `EscrowState.State` + +```solidity +enum State { + NotInitialized, + SignallingEscrow, + RageQuitEscrow +} +``` + +Encodes the current state of an `Escrow` instance. The `NotInitialized` value is expected to apply only to the master copy implementation of the `Escrow` contract. At any given time, one instance must be in the `SignallingEscrow` state, while zero or more instances may be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.initialize` + +```solidity +function initialize(Duration minAssetsLockDuration) +``` + +The `Escrow` instance is intended to be used behind [minimal proxy contracts](https://eips.ethereum.org/EIPS/eip-1167). This method initializes a proxy instance in the `SignallingEscrow` state with the specified minimum assets lock duration. The method can be called only once and is designed for use by the `DualGovernance` contract. + +#### Preconditions + +- MUST be called using the proxy contract. +- MUST be called by the `DualGovernance` contract. +- MUST NOT have been initialized previously. + +--- + +### Function: `Escrow.getEscrowState` + +```solidity +function getEscrowState() view returns (EscrowState.State) +``` + +Returns the current state of the `Escrow` instance, as defined by the `EscrowState.State` enum. + +--- + +### Function: `Escrow.lockStETH` ```solidity! function lockStETH(uint256 amount) external returns (uint256 lockedStETHShares) @@ -524,7 +870,7 @@ function lockStETH(uint256 amount) external returns (uint256 lockedStETHShares) Transfers the specified `amount` of stETH from the caller's (i.e., `msg.sender`) account into the `SignallingEscrow` instance of the `Escrow` contract. -The total rage quit support is updated proportionally to the number of shares corresponding to the locked stETH (see the `Escrow.getRageQuitSupport()` function for the details). For the correct rage quit support calculation, the function updates the number of locked stETH shares in the protocol as follows: +The total rage quit support is updated proportionally to the number of shares corresponding to the locked stETH (see the `Escrow.getRageQuitSupport` function for the details). For the correct rage quit support calculation, the function updates the number of locked stETH shares in the protocol as follows: ```solidity amountInShares = stETH.getSharesByPooledEther(amount); @@ -535,10 +881,10 @@ stETHTotals.lockedShares += amountInShares; The rage quit support will be dynamically updated to reflect changes in the stETH balance due to protocol rewards or validators slashing. -The method calls the `DualGovernance.activateNextState()` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. +The method calls the `DualGovernance.activateNextState` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.lockStETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.lockStETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Returns @@ -551,7 +897,9 @@ The amount of stETH shares locked by the caller during the current method call. - The locked `amount` MUST NOT exceed the caller's stETH balance. - The `DualGovernance` contract MUST NOT have a pending state transition to the `RageQuit` state. -### Function: Escrow.unlockStETH +--- + +### Function: `Escrow.unlockStETH` ```solidity function unlockStETH() external returns (uint256 unlockedStETHShares) @@ -566,10 +914,10 @@ stETHTotals.lockedShares -= _assets[msg.sender].stETHLockedShares; assets[msg.sender].stETHLockedShares = 0; ``` -Additionally, the function triggers the `DualGovernance.activateNextState()` function at the beginning and end of the execution. +Additionally, the function triggers the `DualGovernance.activateNextState` function at the beginning and end of the execution. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.unlockStETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.unlockStETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Returns @@ -582,7 +930,9 @@ The amount of stETH shares unlocked by the caller. - The duration of the `SignallingEscrowMinLockTime` MUST have passed since the caller last invoked any of the methods `Escrow.lockStETH`, `Escrow.lockWstETH`, or `Escrow.lockUnstETH`. - The `DualGovernance` contract MUST NOT have a pending state transition to the `RageQuit` state. -### Function: Escrow.lockWstETH +--- + +### Function: `Escrow.lockWstETH` ```solidity function lockWstETH(uint256 amount) external returns (uint256 lockedStETHShares) @@ -590,21 +940,21 @@ function lockWstETH(uint256 amount) external returns (uint256 lockedStETHShares) Transfers the specified `amount` of wstETH from the caller's (i.e., `msg.sender`) account into the `SignallingEscrow` instance of the `Escrow` contract and unwraps it into the stETH. -The total rage quit support is updated proportionally to the `amount` of locked wstETH (see the `Escrow.getRageQuitSupport()` function for details). For accurate rage quit support calculation, the function updates the number of locked stETH shares in the protocol as follows: +The total rage quit support is updated proportionally to the `amount` of locked wstETH (see the `Escrow.getRageQuitSupport` function for details). For accurate rage quit support calculation, the function updates the number of locked stETH shares in the protocol as follows: ```solidity stETHAmount = WST_ETH.unwrap(amount); -// Use getSharesByPooledEther(), because unwrap() method may transfer 1 wei less amount of stETH +// Use `getSharesByPooledEther`, because `unwrap` method may transfer 1 wei less amount of stETH stETHShares = ST_ETH.getSharesByPooledEth(stETHAmount); assets[msg.sender].stETHLockedShares += stETHShares; stETHTotals.lockedShares += stETHShares; ``` -The method calls the `DualGovernance.activateNextState()` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. +The method calls the `DualGovernance.activateNextState` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.lockWstETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.lockWstETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Returns @@ -617,7 +967,9 @@ The amount of stETH shares locked by the caller during the current method call. - The locked `amount` MUST NOT exceed the caller's wstETH balance. - The `DualGovernance` contract MUST NOT have a pending state transition to the `RageQuit` state. -### Function: Escrow.unlockWstETH +--- + +### Function: `Escrow.unlockWstETH` ```solidity function unlockWstETH() external returns (uint256 unlockedStETHShares) @@ -632,10 +984,10 @@ stETHTotals.lockedShares -= _assets[msg.sender].stETHLockedShares; assets[msg.sender].stETHLockedShares = 0; ``` -Additionally, the function triggers the `DualGovernance.activateNextState()` function at the beginning and end of the execution. +Additionally, the function triggers the `DualGovernance.activateNextState` function at the beginning and end of the execution. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.unlockWstETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.unlockWstETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Returns @@ -649,8 +1001,9 @@ The amount of stETH shares unlocked by the caller. - At least the duration of the `SignallingEscrowMinLockTime` MUST have passed since the caller last invoked any of the methods `Escrow.lockStETH`, `Escrow.lockWstETH`, or `Escrow.lockUnstETH`. - The `DualGovernance` contract MUST NOT have a pending state transition to the `RageQuit` state. +--- -### Function: Escrow.lockUnstETH +### Function: `Escrow.lockUnstETH` ```solidity function lockUnstETH(uint256[] unstETHIds) @@ -659,7 +1012,7 @@ function lockUnstETH(uint256[] unstETHIds) Transfers the withdrawal NFTs with ids contained in the `unstETHIds` from the caller's (i.e. `msg.sender`) account into the `SignallingEscrow` instance of the `Escrow` contract. -To correctly calculate the rage quit support (see the `Escrow.getRageQuitSupport()` function for the details), updates the number of locked withdrawal NFT shares in the protocol for each withdrawal NFT in the `unstETHIds`, as follows: +To correctly calculate the rage quit support (see the `Escrow.getRageQuitSupport` function for the details), updates the number of locked withdrawal NFT shares in the protocol for each withdrawal NFT in the `unstETHIds`, as follows: ```solidity uint256 amountOfShares = withdrawalRequests[id].amountOfShares; @@ -668,21 +1021,23 @@ assets[msg.sender].unstETHLockedShares += amountOfShares; unstETHTotals.unfinalizedShares += amountOfShares; ``` -The method calls the `DualGovernance.activateNextState()` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. +The method calls the `DualGovernance.activateNextState` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.lockUnstETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.lockUnstETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, locking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Preconditions - The `Escrow` instance MUST be in the `SignallingEscrow` state. - The caller MUST be the owner of all withdrawal NFTs with the given ids. -- The caller MUST grant permission to the `SignallingEscrow` instance to transfer tokens with the given ids (`approve()` or `setApprovalForAll()`). +- The caller MUST grant permission to the `SignallingEscrow` instance to transfer tokens with the given ids (`approve` or `setApprovalForAll`). - The passed ids MUST NOT contain the finalized or claimed withdrawal NFTs. - The passed ids MUST NOT contain duplicates. - The `DualGovernance` contract MUST NOT have a pending state transition to the `RageQuit` state. -### Function: Escrow.unlockUnstETH +--- + +### Function: `Escrow.unlockUnstETH` ```solidity function unlockUnstETH(uint256[] unstETHIds) @@ -690,9 +1045,9 @@ function unlockUnstETH(uint256[] unstETHIds) Allows the caller (i.e. `msg.sender`) to unlock a set of previously locked withdrawal NFTs with ids `unstETHIds` from the `SignallingEscrow` instance of the `Escrow` contract. -To correctly calculate the rage quit support (see the `Escrow.getRageQuitSupport()` function for details), updates the number of locked withdrawal NFT shares in the protocol for each withdrawal NFT in the `unstETHIds`, as follows: +To correctly calculate the rage quit support (see the `Escrow.getRageQuitSupport` function for details), updates the number of locked withdrawal NFT shares in the protocol for each withdrawal NFT in the `unstETHIds`, as follows: -- If the withdrawal NFT was marked as finalized (see the `Escrow.markUnstETHFinalized()` function for details): +- If the withdrawal NFT was marked as finalized (see the `Escrow.markUnstETHFinalized` function for details): ```solidity uint256 amountOfShares = withdrawalRequests[id].amountOfShares; @@ -712,10 +1067,10 @@ assets[msg.sender].unstETHLockedShares -= amountOfShares; unstETHTotals.unfinalizedShares -= amountOfShares; ``` -Additionally, the function triggers the `DualGovernance.activateNextState()` function at the beginning and end of the execution. +Additionally, the function triggers the `DualGovernance.activateNextState` function at the beginning and end of the execution. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.unlockUnstETH()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.unlockUnstETH` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, unlocking funds in the `SignallingEscrow` is no longer possible and will revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Preconditions @@ -723,7 +1078,9 @@ Additionally, the function triggers the `DualGovernance.activateNextState()` fun - Each provided withdrawal NFT MUST have been previously locked by the caller. - At least the duration of the `SignallingEscrowMinLockTime` MUST have passed since the caller last invoked any of the methods `Escrow.lockStETH`, `Escrow.lockWstETH`, or `Escrow.lockUnstETH`. -### Function Escrow.markUnstETHFinalized +--- + +### Function: `Escrow.markUnstETHFinalized` ```solidity function markUnstETHFinalized(uint256[] unstETHIds, uint256[] hints) @@ -754,16 +1111,52 @@ Withdrawal NFTs belonging to any of the following categories are excluded from t - Withdrawal NFTs already marked as finalized - Withdrawal NFTs not locked in the `Escrow` instance -The method calls the `DualGovernance.activateNextState()` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. +The method calls the `DualGovernance.activateNextState` function at the beginning and end of the execution, which may transition the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. > [!IMPORTANT] -> To mitigate possible failures when calling the `Escrow.markUnstETHFinalized()` method, it SHOULD be used alongside the `DualGovernance.getPersistedState()`/`DualGovernance.getEffectiveState()` methods or the `DualGovernance.getStateDetails()` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, calling methods that change Rage Quit support in the `SignallingEscrow` will no longer be possible and will result in a revert. In such cases, `DualGovernance.activateNextState()` MUST be called to initiate the pending `RageQuit`. +> To mitigate possible failures when calling the `Escrow.markUnstETHFinalized` method, it SHOULD be used alongside the `DualGovernance.getPersistedState`/`DualGovernance.getEffectiveState` methods or the `DualGovernance.getStateDetails` method. These methods help identify scenarios where `persistedState != RageQuit` but `effectiveState == RageQuit`. When this state is detected, calling methods that change Rage Quit support in the `SignallingEscrow` will no longer be possible and will result in a revert. In such cases, `DualGovernance.activateNextState` MUST be called to initiate the pending `RageQuit`. #### Preconditions - The `Escrow` instance MUST be in the `SignallingEscrow` state. -### Function Escrow.getRageQuitSupport() +--- + +### Function: `Escrow.startRageQuit` + +```solidity +function startRageQuit( + Duration rageQuitExtensionPeriodDuration, + Duration rageQuitEthWithdrawalsDelay +) +``` + +Transits the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. Following this transition, locked funds become unwithdrawable and are accessible to users only as plain ETH after the completion of the full `RageQuit` process, including the `RageQuitExtensionPeriod` and `RageQuitEthWithdrawalsDelay` stages. + +#### Preconditions + +- Method MUST be called by the `DualGovernance` contract. +- The `Escrow` instance MUST be in the `SignallingEscrow` state. + +--- + +### Function: `Escrow.setMinAssetsLockDuration` + +```solidity +function setMinAssetsLockDuration(Duration newMinAssetsLockDuration) +``` + +Sets the minimum duration that must elapse after the last stETH, wstETH, or unstETH lock by a vetoer before they are permitted to unlock their assets from the `SignallingEscrow`. + +#### Preconditions + +- Method MUST be called by the `DualGovernance` contract. +- `newMinAssetsLockDuration` MUST NOT be zero. +- `newMinAssetsLockDuration` MUST NOT exceed `Escrow.MAX_MIN_ASSETS_LOCK_DURATION`. + +--- + +### Function: `Escrow.getRageQuitSupport` ```solidity function getRageQuitSupport() view returns (PercentD16) @@ -780,54 +1173,110 @@ where : - `finalizedETH` refers to `unstETHTotals.finalizedETH` - `unfinalizedShares` refers to `stETHTotals.lockedShares + unstETHTotals.unfinalizedShares` -### Function Escrow.startRageQuit +--- + +### Function: `Escrow.getMinAssetsLockDuration` ```solidity -function startRageQuit( - Duration rageQuitExtensionPeriodDuration, - Duration rageQuitEthWithdrawalsDelay -) +function getMinAssetsLockDuration() view returns (Duration minAssetsLockDuration) ``` -Transits the `Escrow` instance from the `SignallingEscrow` state to the `RageQuitEscrow` state. Following this transition, locked funds become unwithdrawable and are accessible to users only as plain ETH after the completion of the full `RageQuit` process, including the `RageQuitExtensionPeriod` and `RageQuitEthWithdrawalsDelay` stages. +Returns the minimum duration that must elapse after the most recent stETH, wstETH, or unstETH lock by a vetoer before they are allowed to unlock their assets from the `SignallingEscrow`. -#### Preconditions +--- -- Method MUST be called by the `DualGovernance` contract. -- The `Escrow` instance MUST be in the `SignallingEscrow` state. +### Function: `Escrow.getVetoerDetails` + +```solidity +function getVetoerDetails(address vetoer) view returns (VetoerDetails memory details) +``` + +Returns the state of locked assets for a specific vetoer. The `VetoerDetails` struct includes the following fields: -### Function Escrow.requestNextWithdrawalsBatch +- `unstETHIdsCount`: The total number of unstETH NFTs locked by the vetoer. +- `stETHLockedShares`: The total number of stETH shares locked by the vetoer. +- `unstETHLockedShares`: The total number of unstETH shares locked by the vetoer. +- `lastAssetsLockTimestamp`: The timestamp of the most recent assets lock by the vetoer. + +--- + +### Function: `Escrow.getVetoerUnstETHIds` + +```solidity +function getVetoerUnstETHIds(address vetoer) view returns (uint256[] memory unstETHIds) +``` + +Returns the ids of the unstETH NFTs locked by the specified vetoer. + +--- + +### Function: `Escrow.getSignallingEscrowDetails` + +```solidity +function getSignallingEscrowDetails() view returns (SignallingEscrowDetails memory details) +``` + +Returns the total amounts of locked and claimed assets in the Escrow. The `SignallingEscrowDetails` struct includes the following fields: + +- `totalStETHClaimedETH`: The total amount of ETH claimed from locked stETH. +- `totalStETHLockedShares`: The total number of stETH shares currently locked in the Escrow. +- `totalUnstETHUnfinalizedShares`: The total number of shares from unstETH NFTs that have not yet been finalized. +- `totalUnstETHFinalizedETH`: The total amount of ETH from finalized unstETH NFTs. + +--- + +### Function: `Escrow.getLockedUnstETHDetails` + +```solidity +function getLockedUnstETHDetails(uint256[] calldata unstETHIds) view returns (LockedUnstETHDetails[] memory unstETHDetails) +``` + +Retrieves details of locked unstETH records for the specified ids. Each `LockedUnstETHDetails` struct includes the following fields: + +- `id`: The id of the locked unstETH NFT. +- `status`: The current status of the unstETH record. This value is described by the `UnstETHRecordStatus` enum, with the following possible values: `NotLocked`, `Locked`, `Finalized`, `Claimed`, and `Withdrawn`. +- `lockedBy`: The address that locked the unstETH record. +- `shares`: The number of shares associated with the locked unstETH. +- `claimableAmount`: The amount of claimable ETH in the unstETH. This value is `0` until the unstETH is finalized or claimed. + +--- + +### Function: `Escrow.requestNextWithdrawalsBatch` ```solidity function requestNextWithdrawalsBatch(uint256 batchSize) ``` -Transfers stETH held in the `RageQuitEscrow` instance into the `WithdrawalQueue`. The function may be invoked multiple times until all stETH is converted into withdrawal NFTs. For each withdrawal NFT, the owner is set to `Escrow` contract instance. Each call creates `batchSize` withdrawal requests (except the final one, which may contain fewer items), where each withdrawal request size equals `WithdrawalQueue.MAX_STETH_WITHDRAWAL_AMOUNT()`, except for potentially the last batch, which may have a smaller size. +Transfers stETH held in the `RageQuitEscrow` instance into the `WithdrawalQueue`. The function may be invoked multiple times until all stETH is converted into withdrawal NFTs. For each withdrawal NFT, the owner is set to `Escrow` contract instance. Each call creates `batchSize` withdrawal requests (except the final one, which may contain fewer items), where each withdrawal request size equals `WithdrawalQueue.MAX_STETH_WITHDRAWAL_AMOUNT`, except for potentially the last batch, which may have a smaller size. -Upon execution, the function tracks the ids of the withdrawal requests generated by all invocations. When the remaining stETH balance on the contract falls below `max(_MIN_TRANSFERRABLE_ST_ETH_AMOUNT, WITHDRAWAL_QUEUE.MIN_STETH_WITHDRAWAL_AMOUNT())`, the generation of withdrawal batches is concluded, and subsequent function calls will revert. +Upon execution, the function tracks the ids of the withdrawal requests generated by all invocations. When the remaining stETH balance on the contract falls below `max(_MIN_TRANSFERRABLE_ST_ETH_AMOUNT, WITHDRAWAL_QUEUE.MIN_STETH_WITHDRAWAL_AMOUNT)`, the generation of withdrawal batches is concluded, and subsequent function calls will revert. #### Preconditions - The `Escrow` instance MUST be in the `RageQuitEscrow` state. -- The `batchSize` MUST be greater than or equal to `Escrow.MIN_WITHDRAWALS_BATCH_SIZE()`. +- The `batchSize` MUST be greater than or equal to `Escrow.MIN_WITHDRAWALS_BATCH_SIZE`. - The generation of withdrawal request batches MUST not be concluded -### Function Escrow.claimNextWithdrawalsBatch(uint256, uint256[]) +--- + +### Function: `Escrow.claimNextWithdrawalsBatch(uint256, uint256[])` ```solidity function claimNextWithdrawalsBatch(uint256 fromUnstETHId, uint256[] hints) ``` -Allows users to claim finalized withdrawal NFTs generated by the `Escrow.requestNextWithdrawalsBatch()` function. +Allows users to claim finalized withdrawal NFTs generated by the `Escrow.requestNextWithdrawalsBatch` function. This function updates the `stETHTotals.claimedETH` variable to track the total amount of claimed ETH. #### Preconditions - The `Escrow` instance MUST be in the `RageQuitEscrow` state. -- The `fromUnstETHId` MUST be equal to the id of the first unclaimed withdrawal NFT locked in the `Escrow`. The ids of the unclaimed withdrawal NFTs can be retrieved via the `getNextWithdrawalBatch()` method. +- The `fromUnstETHId` MUST be equal to the id of the first unclaimed withdrawal NFT locked in the `Escrow`. The ids of the unclaimed withdrawal NFTs can be retrieved via the `getNextWithdrawalBatch` method. - There MUST be at least one unclaimed withdrawal NFT. -### Function Escrow.claimNextWithdrawalsBatch(uint256) +--- + +### Function: `Escrow.claimNextWithdrawalsBatch(uint256)` ```solidity function claimNextWithdrawalsBatch(uint256 maxUnstETHIdsCount) @@ -835,46 +1284,41 @@ function claimNextWithdrawalsBatch(uint256 maxUnstETHIdsCount) This is an overload version of `Escrow.claimNextWithdrawalsBatch(uint256, uint256[])`. It retrieves hints for processing the withdrawal NFTs on-chain. -### Function Escrow.claimUnstETH +--- + +### Function: `Escrow.startRageQuitExtensionPeriod` ```solidity -function claimUnstETH(uint256[] unstETHIds, uint256[] hints) +function startRageQuitExtensionPeriod() ``` -Allows users to claim the ETH associated with finalized withdrawal NFTs with ids `unstETHIds` locked in the `Escrow` contract. Upon calling this function, the claimed ETH is transferred to the `Escrow` contract instance. - -To safeguard the ETH associated with withdrawal NFTs, this function should be invoked when the `Escrow` is in the `RageQuitEscrow` state and before the `RageQuitExtensionPeriod` ends. The ETH corresponding to unclaimed withdrawal NFTs after this period ends would still be controlled by the code potentially affected by pending and future DAO decisions. +Initiates the `RageQuitExtensionPeriod` once all withdrawal batches have been claimed. In cases where the `Escrow` instance only has locked unstETH NFTs, it verifies that the last unstETH NFT registered in the `WithdrawalQueue` at the time of the `Escrow.startRageQuit` call is finalized. This ensures that every unstETH NFT locked in the Escrow can be claimed by the user during the `RageQuitExtensionPeriod`. #### Preconditions +- All withdrawal batches MUST be formed using the `Escrow.requestNextWithdrawalsBatch`. +- The last unstETH NFT in the `WithdrawalQueue` at the time of the `Escrow.startRageQuit` call MUST be finalized. +- All withdrawal batches generated during `Escrow.requestNextWithdrawalsBatch` MUST be claimed. -- The `Escrow` instance MUST be in the `RageQuitEscrow` state. -- The provided `unstETHIds` MUST only contain finalized but unclaimed withdrawal requests with the owner set to `msg.sender`. +--- -### Function Escrow.startRageQuitExtensionPeriod +### Function: `Escrow.claimUnstETH` ```solidity -function startRageQuitExtensionPeriod() +function claimUnstETH(uint256[] unstETHIds, uint256[] hints) ``` -Initiates the `RageQuitExtensionPeriod` once all withdrawal batches have been claimed. In cases where the `Escrow` instance only has locked unstETH NFTs, it verifies that the last unstETH NFT registered in the `WithdrawalQueue` at the time of the `Escrow.startRageQuit()` call is finalized. This ensures that every unstETH NFT locked in the Escrow can be claimed by the user during the `RageQuitExtensionPeriod`. +Allows users to claim the ETH associated with finalized withdrawal NFTs with ids `unstETHIds` locked in the `Escrow` contract. Upon calling this function, the claimed ETH is transferred to the `Escrow` contract instance. -#### Preconditions -- All withdrawal batches MUST be formed using the `Escrow.requestNextWithdrawalsBatch()`. -- The last unstETH NFT in the `WithdrawalQueue` at the time of the `Escrow.startRageQuit()` call MUST be finalized. -- All withdrawal batches generated during `Escrow.requestNextWithdrawalsBatch()` MUST be claimed. +To safeguard the ETH associated with withdrawal NFTs, this function should be invoked when the `Escrow` is in the `RageQuitEscrow` state and before the `RageQuitExtensionPeriod` ends. The ETH corresponding to unclaimed withdrawal NFTs after this period ends would still be controlled by the code potentially affected by pending and future DAO decisions. -### Function Escrow.isRageQuitFinalized +#### Preconditions -```solidity -function isRageQuitFinalized() view returns (bool) -``` +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. +- The provided `unstETHIds` MUST only contain finalized but unclaimed withdrawal requests with the owner set to `msg.sender`. -Returns whether the rage quit process has been finalized. The rage quit process is considered finalized when all the following conditions are met: -- The `Escrow` instance is in the `RageQuitEscrow` state. -- All withdrawal request batches have been claimed. -- The duration of the `RageQuitExtensionPeriod` has elapsed. +--- -### Function Escrow.withdrawETH +### Function: `Escrow.withdrawETH` ```solidity function withdrawETH() @@ -896,7 +1340,9 @@ return stETHTotals.claimedETH * assets[msg.sender].stETHLockedShares - The `RageQuitEthWithdrawalsDelay` period MUST be elapsed after the expiration of the `RageQuitExtensionPeriod` duration. - The caller MUST have a non-zero amount of stETH shares to withdraw. -### Function Escrow.withdrawETH() +--- + +### Function: `Escrow.withdrawETH(uint256[])` ```solidity function withdrawETH(uint256[] unstETHIds) @@ -906,29 +1352,122 @@ Allows the caller (i.e. `msg.sender`) to withdraw the claimed ETH from the withd #### Preconditions +- The `unstETHIds` array length MUST be greater than zero. - The `Escrow` instance MUST be in the `RageQuitEscrow` state. - The rage quit process MUST be completed, including the expiration of the `RageQuitExtensionPeriod` duration. - The `RageQuitEthWithdrawalsDelay` period MUST be elapsed after the expiration of the `RageQuitExtensionPeriod` duration. - The caller MUST be set as the owner of the provided NFTs. -- Each withdrawal NFT MUST have been claimed using the `Escrow.claimUnstETH()` function. +- Each withdrawal NFT MUST have been claimed using the `Escrow.claimUnstETH` function. - Withdrawal NFTs must not have been withdrawn previously. +--- + +### Function: `Escrow.getNextWithdrawalBatch` + +```solidity +function getNextWithdrawalBatch(uint256 limit) view returns (uint256[] memory unstETHIds) +``` + +Returns the ids of the next batch of unstETH NFTs available for claiming. The `limit` parameter specifies the maximum number of ids to include in the resulting array. + +#### Preconditions + +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.isWithdrawalsBatchesClosed` + +```solidity +function isWithdrawalsBatchesClosed() view returns (bool) +``` -## Contract: EmergencyProtectedTimelock.sol +Returns whether all withdrawal batches have been closed. + +#### Preconditions + +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.getUnclaimedUnstETHIdsCount` + +```solidity +function getUnclaimedUnstETHIdsCount() view returns (uint256) +``` + +Returns the total number of unstETH NFTs that have not yet been claimed. + +#### Preconditions + +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.isRageQuitFinalized` + +```solidity +function isRageQuitFinalized() view returns (bool) +``` + +Returns whether the rage quit process has been finalized. The rage quit process is considered finalized when all the following conditions are met: +- The `Escrow` instance is in the `RageQuitEscrow` state. +- All withdrawal request batches have been claimed. +- The duration of the `RageQuitExtensionPeriod` has elapsed. + +#### Preconditions + +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.getRageQuitEscrowDetails` + +```solidity +function getRageQuitEscrowDetails() view returns (RageQuitEscrowDetails memory details) +``` + +Returns details about the current state of the rage quit escrow. The `RageQuitEscrowDetails` struct includes the following fields: + +- `isRageQuitExtensionPeriodStarted`: A boolean indicating whether the rage quit extension period has started. +- `rageQuitEthWithdrawalsDelay`: The delay period (in seconds) for ETH withdrawals during the rage quit process. +- `rageQuitExtensionPeriodDuration`: The duration (in seconds) of the rage quit extension period. +- `rageQuitExtensionPeriodStartedAt`: The timestamp when the rage quit extension period started. + +#### Preconditions + +- The `Escrow` instance MUST be in the `RageQuitEscrow` state. + +--- + +### Function: `Escrow.receive` + +```solidity +receive() external payable +``` + +Accepts ETH payments exclusively from the `WithdrawalQueue` contract. + +#### Preconditions + +- The ETH sender MUST be the address of the `WithdrawalQueue` contract. + + +## Contract: EmergencyProtectedTimelock `EmergencyProtectedTimelock` is the singleton instance storing proposals approved by DAO voting systems and submitted to the Dual Governance. It allows for setting up time-bound **Emergency Activation Committee** and **Emergency Execution Committee**, acting as safeguards for the case of zero-day vulnerability in Dual Governance contracts. For a proposal to be executed, the following steps have to be performed in order: 1. The proposal must be submitted using the `EmergencyProtectedTimelock.submit` function. -2. The configured post-submit timelock (`EmergencyProtectedTimelock.getAfterSubmitDelay()`) must elapse. +2. The configured post-submit timelock (`EmergencyProtectedTimelock.getAfterSubmitDelay`) must elapse. 3. The proposal must be scheduled using the `EmergencyProtectedTimelock.schedule` function. -4. The configured emergency protection delay (`EmergencyProtectedTimelock.getAfterScheduleDelay()`) must elapse (can be zero, see below). +4. The configured emergency protection delay (`EmergencyProtectedTimelock.getAfterScheduleDelay`) must elapse (can be zero, see below). 5. The proposal must be executed using the `EmergencyProtectedTimelock.execute` function. -The contract only allows proposal submission and scheduling by the `governance` address. Normally, this address points to the [`DualGovernance`](#Contract-DualGovernancesol) singleton instance. Proposal execution is permissionless, unless Emergency Mode is activated. +The contract only allows proposal submission and scheduling by the `governance` address. Normally, this address points to the [`DualGovernance`](#Contract-DualGovernances) singleton instance. Proposal execution is permissionless, unless Emergency Mode is activated. -If the Emergency Committees are set up and active, the governance proposal gets a separate emergency protection delay between submitting and scheduling. This additional timelock is implemented in the `EmergencyProtectedTimelock` contract to protect from zero-day vulnerability in the logic of `DualGovernance.sol` and other core DG contracts. If the Emergency Committees aren't set, the proposal flow is the same, but the timelock duration is zero. +If the Emergency Committees are set up and active, the `EmergencyProtectedTimelock` may be configured, making governance proposal getting a separate emergency protection delay between submitting and scheduling. This additional timelock is implemented in the `EmergencyProtectedTimelock` contract to protect from zero-day vulnerability in the logic of `DualGovernance` and other core DG contracts. If the Emergency Committees aren't set, the proposal flow is the same, and the timelock duration may be set to zero. Emergency Activation Committee, while active, can enable the Emergency Mode. This mode prohibits anyone but the Emergency Execution Committee from executing proposals. It also allows the Emergency Execution Committee to reset the governance, effectively disabling the Dual Governance subsystem. @@ -936,41 +1475,47 @@ The governance reset entails the following steps: 1. Clearing both the Emergency Activation and Execution Committees from the `EmergencyProtectedTimelock`. 2. Cancelling all proposals that have not been executed. -3. Setting the `governance` address to a pre-configured Emergency Governance address. In the simplest scenario, this would be the Lido DAO Aragon Voting contract. +3. Setting the `governance` address to a pre-configured Emergency Governance address. In the simplest scenario, this would be the instance of the [`TimelockedGovernance`](plan-b.md#contract-timelockedgovernance) contract connected to the Lido DAO Aragon Voting contract. -### Function: EmergencyProtectedTimelock.submit +--- + +### Function: `EmergencyProtectedTimelock.submit` ```solidity -function submit(address executor, ExecutorCall[] calls) +function submit(address executor, ExternalCall[] calls) returns (uint256 proposalId) ``` -Registers a new governance proposal composed of one or more EVM `calls` to be made by the `executor` contract. +Registers a new governance proposal consisting of one or more EVM `calls` to be executed by the specified `executor` contract. #### Returns -The ID of the successfully registered proposal. - +The id of the successfully registered proposal. #### Preconditions -* MUST be called by the `governance` address. +- MUST be called by the `governance` address. +- The `calls` array length MUST be greater than zero. +--- -### Function: EmergencyProtectedTimelock.schedule +### Function: `EmergencyProtectedTimelock.schedule` ```solidity function schedule(uint256 proposalId) ``` +Schedules a previously submitted and non-cancelled proposal for execution after the required delay has passed. + #### Preconditions -* MUST be called by the `governance` address. -* The proposal MUST be already submitted. -* The post-submit timelock MUST already elapse since the moment the proposal was submitted. +- MUST be called by the `governance` address. +- The proposal MUST already be submitted. +- The post-submit timelock MUST have elapsed since the proposal submission. +--- -### Function: EmergencyProtectedTimelock.execute +### Function: `EmergencyProtectedTimelock.execute` ```solidity function execute(uint256 proposalId) @@ -980,11 +1525,13 @@ Instructs the executor contract associated with the proposal to issue the propos #### Preconditions -* Emergency mode MUST NOT be active. -* The proposal MUST be already submitted & scheduled for execution. -* The emergency protection delay MUST already elapse since the moment the proposal was scheduled. +- Emergency mode MUST NOT be active. +- The proposal MUST be already submitted & scheduled for execution. +- The emergency protection delay MUST already elapse since the moment the proposal was scheduled. + +--- -### Function: EmergencyProtectedTimelock.cancelAllNonExecutedProposals +### Function: `EmergencyProtectedTimelock.cancelAllNonExecutedProposals` ```solidity function cancelAllNonExecutedProposals() @@ -994,9 +1541,154 @@ Cancels all non-executed proposal, making them forever non-executable. #### Preconditions -* MUST be called by the `governance` address. +- MUST be called by the `governance` address. + +--- + +### Function: `EmergencyProtectedTimelock.setGovernance` + +```solidity +function setGovernance(address newGovernance) +``` + +Updates the address of the `governance` and cancels all non-executed proposals. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newGovernance` address MUST NOT be the zero address. +- The `newGovernance` address MUST NOT be the same as the current value. -### Function: EmergencyProtectedTimelock.activateEmergencyMode +--- + +### Function: `EmergencyProtectedTimelock.setAfterSubmitDelay` + +```solidity +function setAfterSubmitDelay(Duration newAfterSubmitDelay) +``` + +Sets the delay required between the submission of a proposal and its scheduling for execution. Ensures that the new delay value complies with the defined sanity check bounds. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newAfterSubmitDelay` duration MUST NOT exceed the `EmergencyProtectedTimelock.MAX_AFTER_SUBMIT_DELAY` value. +- The `newAfterSubmitDelay` duration MUST NOT be the same as the current value. +- After the update, the sum of `afterSubmitDelay` and `afterScheduleDelay` MUST NOT be less than the `EmergencyProtectedTimelock.MIN_EXECUTION_DELAY`. + +--- + +### Function: `EmergencyProtectedTimelock.setAfterScheduleDelay` + +```solidity +function setAfterScheduleDelay(Duration newAfterScheduleDelay) +``` + +Sets the delay required to pass from the scheduling of a proposal before it can be executed. Ensures that the new delay value complies with the defined sanity check bounds. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newAfterScheduleDelay` duration MUST NOT exceed the `EmergencyProtectedTimelock.MAX_AFTER_SCHEDULE_DELAY` value. +- The `newAfterScheduleDelay` duration MUST NOT be the same as the current value. +- After the update, the sum of `afterSubmitDelay` and `afterScheduleDelay` MUST NOT be less than the `EmergencyProtectedTimelock.MIN_EXECUTION_DELAY`. + +--- + +### Function: `EmergencyProtectedTimelock.transferExecutorOwnership` + +```solidity +function transferExecutorOwnership(address executor, address owner) +``` + +Transfers ownership of the specified executor contract to a new owner. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `executor` MUST implement the `IOwnable` interface. +- The current owner of the `executor` (`executor.owner`) MUST be the address of the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionActivationCommittee` + +```solidity +function setEmergencyProtectionActivationCommittee(address newEmergencyActivationCommittee) +``` + +Sets the address of the emergency activation committee. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyActivationCommittee` duration MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionExecutionCommittee` + +```solidity +function setEmergencyProtectionExecutionCommittee(address newEmergencyExecutionCommittee) +``` + +Sets the address of the emergency execution committee. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyExecutionCommittee` address MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyProtectionEndDate` + +```solidity +function setEmergencyProtectionEndDate(Timestamp newEmergencyProtectionEndDate) +``` + +Sets the end date for the emergency protection period. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyProtectionEndDate` MUST NOT be farther in the future than `EmergencyProtectedTimelock.MAX_EMERGENCY_PROTECTION_DURATION` from the `block.timestamp` at the time of method invocation. +- The `newEmergencyProtectionEndDate` MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyModeDuration` + +```solidity +function setEmergencyModeDuration(Duration newEmergencyModeDuration) +``` + +Sets the duration of the emergency mode. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyModeDuration` MUST NOT exceed the `EmergencyProtectedTimelock.MAX_EMERGENCY_MODE_DURATION` duration. +- The `newEmergencyModeDuration` MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.setEmergencyGovernance` + +```solidity +function setEmergencyGovernance(address newEmergencyGovernance) +``` + +Sets the address of the emergency governance contract. + +#### Preconditions + +- MUST be called by the admin executor contract. +- The `newEmergencyGovernance` address MUST NOT be the same as the current value. + +--- + +### Function: `EmergencyProtectedTimelock.activateEmergencyMode` ```solidity function activateEmergencyMode() @@ -1006,10 +1698,12 @@ Activates the Emergency Mode. #### Preconditions -* MUST be called by the Emergency Activation Committee address. -* The Emergency Mode MUST NOT be active. +- MUST be called by the Emergency Activation Committee address. +- The Emergency Mode MUST NOT be active. -### Function: EmergencyProtectedTimelock.emergencyExecute +--- + +### Function: `EmergencyProtectedTimelock.emergencyExecute` ```solidity function emergencyExecute(uint256 proposalId) @@ -1019,10 +1713,12 @@ Executes the scheduled proposal, bypassing the post-schedule delay. #### Preconditions -* MUST be called by the Emergency Execution Committee address. -* The Emergency Mode MUST be active. +- MUST be called by the Emergency Execution Committee address. +- The Emergency Mode MUST be active. + +--- -### Function: EmergencyProtectedTimelock.deactivateEmergencyMode +### Function: `EmergencyProtectedTimelock.deactivateEmergencyMode` ```solidity function deactivateEmergencyMode() @@ -1032,10 +1728,12 @@ Deactivates the Emergency Activation and Emergency Execution Committees (setting #### Preconditions -* The Emergency Mode MUST be active. -* If the Emergency Mode was activated less than the `emergency mode max duration` ago, MUST be called by the [Admin Executor](#Administrative-actions) address. +- The Emergency Mode MUST be active. +- If the Emergency Mode was activated less than the `emergency mode max duration` ago, MUST be called by the [Admin Executor](#Administrative-actions) address. -### Function: EmergencyProtectedTimelock.emergencyReset +--- + +### Function: `EmergencyProtectedTimelock.emergencyReset` ```solidity function emergencyReset() @@ -1045,30 +1743,255 @@ Resets the `governance` address to the `EMERGENCY_GOVERNANCE` value defined in t #### Preconditions -* The Emergency Mode MUST be active. -* MUST be called by the Emergency Execution Committee address. +- The Emergency Mode MUST be active. +- MUST be called by the Emergency Execution Committee address. + +--- + +### Function: `EmergencyProtectedTimelock.isEmergencyProtectionEnabled` + +```solidity +function isEmergencyProtectionEnabled() view returns (bool) +``` + +Returns whether emergency protection is currently enabled. + +--- + +### Function: `EmergencyProtectedTimelock.isEmergencyModeActive` + +```solidity +function isEmergencyModeActive() view returns (bool) +``` + +Returns whether the system is currently in Emergency Mode. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyProtectionDetails` + +```solidity +function getEmergencyProtectionDetails() view returns (EmergencyProtectionDetails memory details) +``` + +Returns details about the current state of emergency protection. The `EmergencyProtectionDetails` struct includes the following fields: + +- `emergencyModeDuration`: The duration for which the emergency mode remains active after activation. +- `emergencyModeEndsAfter`: The timestamp indicating when the current emergency mode will end. +- `emergencyProtectionEndsAfter`: The timestamp indicating when the overall emergency protection period will expire. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyGovernance` + +```solidity +function getEmergencyGovernance() view returns (address) +``` + +Returns the address of the emergency governance contract. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyActivationCommittee` + +```solidity +function getEmergencyActivationCommittee() view returns (address) +``` + +Returns the address of the emergency activation committee. + +--- + +### Function: `EmergencyProtectedTimelock.getEmergencyExecutionCommittee` + +```solidity +function getEmergencyExecutionCommittee() view returns (address) +``` + +Returns the address of the emergency execution committee. + +--- + +### Function: `EmergencyProtectedTimelock.getGovernance` + +```solidity +function getGovernance() view returns (address) +``` + +Returns the address of the current governance contract. + +--- + +### Function: `EmergencyProtectedTimelock.getAdminExecutor` + +```solidity +function getAdminExecutor() view returns (address) +``` + +Returns the address of the admin executor contract. + +--- + +### Function: `EmergencyProtectedTimelock.getAfterSubmitDelay` + +```solidity +function getAfterSubmitDelay() view returns (Duration) +``` + +Returns the configured delay duration required before a submitted proposal can be scheduled. + +--- + +### Function: `EmergencyProtectedTimelock.getAfterScheduleDelay` + +```solidity +function getAfterScheduleDelay() view returns (Duration) +``` + +Returns the configured delay duration required before a scheduled proposal can be executed. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalDetails` + +```solidity +function getProposalDetails(uint256 proposalId) view returns (ProposalDetails memory details) +``` + +Returns information about a proposal, excluding the external calls associated with it. The `ProposalDetails` struct includes the following fields: + +- `id`: The id of the proposal. +- `status`: The current status of the proposal. Possible values are: + - `1`: The proposal was submitted but not scheduled. + - `2`: The proposal was submitted and scheduled but not yet executed. + - `3`: The proposal was submitted, scheduled, and executed. This is the final state of the proposal lifecycle. + - `4`: The proposal was cancelled via `cancelAllNonExecutedProposals` and cannot be scheduled or executed anymore. This is the final state of the proposal lifecycle. +- `executor`: The address of the executor responsible for executing the proposal's external calls. +- `submittedAt`: The timestamp when the proposal was submitted. +- `scheduledAt`: The timestamp when the proposal was scheduled for execution. This value is `0` if the proposal was submitted but not yet scheduled. + +#### Preconditions + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalCalls` + +```solidity +function getProposalCalls(uint256 proposalId) view returns (ExternalCall[] memory calls) +``` + +Returns the EVM calls associated with the specified proposal. See the [Struct: ExternalCall](#Struct-ExternalCall) for details on the structure of each call. + +#### Preconditions + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposal` + +```solidity +function getProposal(uint256 proposalId) view returns + (ProposalDetails memory proposalDetails, ExternalCall[] memory calls) +``` + +Retrieves the details of a proposal, including the associated calls to be executed, identified by the proposal's id. + +#### Returns + +- `proposalDetails`: A `ProposalDetails` struct containing metadata and state information about the proposal. +- `calls`: An array of `ExternalCall` structs representing the EVM calls associated with the proposal. + +#### Preconditions + +- The proposal with the `proposalId` MUST have been previously submitted into the `EmergencyProtectedTimelock` instance. + +--- + +### Function: `EmergencyProtectedTimelock.getProposalsCount` + +```solidity +function getProposalsCount() view returns (uint256 count) +``` + +Returns the total number of proposals submitted to the system. + +--- + +### Function: `EmergencyProtectedTimelock.canExecute` + +```solidity +function canExecute(uint256 proposalId) view returns (bool) +``` + +Checks whether the specified proposal can be executed. + +--- + +### Function: `EmergencyProtectedTimelock.canSchedule` + +```solidity +function canSchedule(uint256 proposalId) view returns (bool) +``` + +Checks whether the specified proposal can be scheduled. + +--- + +### Function: `EmergencyProtectedTimelock.setAdminExecutor` + +```solidity +function setAdminExecutor(address newAdminExecutor) +``` + +Sets a new address for the admin executor contract. + +#### Preconditions + +- MUST be called by the current admin executor contract. +- The `newAdminExecutor` address MUST NOT be the zero address. +- The `newAdminExecutor` address MUST NOT be the same as the current value. -### Admin functions +--- -The contract has the interface for managing the configuration related to emergency protection (`setEmergencyProtectionActivationCommittee`, `setEmergencyProtectionExecutionCommittee`, `setEmergencyProtectionEndDate`, `setEmergencyModeDuration`, `setEmergencyGovernance`) and general system wiring (`transferExecutorOwnership`, `setGovernance`, `setAfterSubmitDelay`, `setAfterScheduleDelay`). These functions MUST be called by the [Admin Executor](#Administrative-actions) address, basically routing any such changes through the Dual Governance mechanics. +## Contract: `ImmutableDualGovernanceConfigProvider` -## Contract: ImmutableDualGovernanceConfigProvider.sol +`ImmutableDualGovernanceConfigProvider` is a smart contract that stores all the constants used in the Dual Governance system and provides an interface for accessing them. It implements the `IDualGovernanceConfigProvider` interface. -`ImmutableDualGovernanceConfigProvider.sol` is a smart contract that stores all the constants used in the Dual Governance system and provides an interface for accessing them. It implements the `IDualGovernanceConfigProvider` interface. +--- -### Function: ImmutableDualGovernanceConfigProvider.getDualGovernanceConfig +### Function: `ImmutableDualGovernanceConfigProvider.getDualGovernanceConfig` ```solidity function getDualGovernanceConfig() view returns (DualGovernanceConfig.Context memory config) ``` -This function provides the configuration settings required for the proper functioning of the DualGovernance contract, ensuring that the system can access the necessary context and parameters for managing state transitions. +Provides the configuration settings required for the proper functioning of the `DualGovernance` contract. These settings ensure that the system has access to the necessary context and parameters for managing state transitions. The `DualGovernanceConfig.Context` includes the following fields: + +- `firstSealRageQuitSupport`: The percentage of the total stETH supply that must be reached in the Signalling Escrow to transition Dual Governance from the `Normal` state to the `VetoSignalling` state. +- `secondSealRageQuitSupport`: The percentage of the total stETH supply that must be reached in the Signalling Escrow to transition Dual Governance into the `RageQuit` state. +- `minAssetsLockDuration`: The minimum duration that assets must remain locked in the Signalling Escrow before unlocking is permitted. +- `vetoSignallingMinDuration`: The minimum duration of the `VetoSignalling` state. +- `vetoSignallingMaxDuration`: The maximum duration of the `VetoSignalling` state. +- `vetoSignallingMinActiveDuration`: The minimum duration of the `VetoSignalling` state before it can be exited. Once in the `VetoSignalling` state, it cannot be exited sooner than this duration. +- `vetoSignallingDeactivationMaxDuration`: The maximum duration of the `VetoSignallingDeactivation` state. +- `vetoCooldownDuration`: The duration of the `VetoCooldown` state. +- `rageQuitExtensionPeriodDuration`: The duration of the Rage Quit Extension Period. +- `rageQuitEthWithdrawalsMinDelay`: The minimum delay for ETH withdrawals after the Rage Quit process completes. +- `rageQuitEthWithdrawalsMaxDelay`: The maximum delay for ETH withdrawals after the Rage Quit process completes. +- `rageQuitEthWithdrawalsDelayGrowth`: The incremental growth of the ETH withdrawal delay with each "continuous" Rage Quit. A Rage Quit is considered continuous if Dual Governance has not re-entered the `Normal` state between two Rage Quits. + +--- -## Contract: ProposalsList.sol +## Contract: `ProposalsList` `ProposalsList` implements storage for list of `Proposal`s with public interface to access. -### Function: ProposalsList.getProposals +--- + +### Function: `ProposalsList.getProposals` ```solidity function getProposals(uint256 offset, uint256 limit) view returns (Proposal[] memory proposals) @@ -1076,7 +1999,9 @@ function getProposals(uint256 offset, uint256 limit) view returns (Proposal[] me Returns a list of `Proposal` objects starting from the specified `offset`, with the number of proposals limited by the `limit` parameter. -### Function: ProposalsList.getProposalAt +--- + +### Function: `ProposalsList.getProposalAt` ```solidity function getProposalAt(uint256 index) view returns (Proposal memory) @@ -1084,7 +2009,9 @@ function getProposalAt(uint256 index) view returns (Proposal memory) Returns the `Proposal` located at the specified `index` in the proposals list. -### Function: ProposalsList.getProposal +--- + +### Function: `ProposalsList.getProposal` ```solidity function getProposal(bytes32 key) view returns (Proposal memory) @@ -1092,7 +2019,9 @@ function getProposal(bytes32 key) view returns (Proposal memory) Returns the `Proposal` identified by its unique `key`. -### Function: ProposalsList.getProposalsLength +--- + +### Function: `ProposalsList.getProposalsLength` ```solidity function getProposalsLength() view returns (uint256) @@ -1100,7 +2029,9 @@ function getProposalsLength() view returns (uint256) Returns the total number of `Proposal` objects created. -### Function: ProposalsList.getOrderedKeys +--- + +### Function: `ProposalsList.getOrderedKeys` ```solidity function getOrderedKeys(uint256 offset, uint256 limit) view returns (bytes32[] memory) @@ -1108,11 +2039,15 @@ function getOrderedKeys(uint256 offset, uint256 limit) view returns (bytes32[] m Returns an ordered list of `Proposal` keys with the given `offset` and `limit` for pagination. -## Contract: HashConsensus.sol +--- + +## Contract: `HashConsensus` `HashConsensus` is an abstract contract that allows for consensus-based decision-making among a set of members. The consensus is achieved by members voting on a specific hash, and decisions can only be executed if a quorum is reached and a timelock period has elapsed. -### Function: HashConsensus.addMembers +--- + +### Function: `HashConsensus.addMembers` ```solidity function addMembers(address[] memory newMembers, uint256 executionQuorum) @@ -1122,11 +2057,13 @@ Adds new members and updates the quorum. #### Preconditions -* Only the owner can call this function. -* Members MUST NOT be part of the set. -* `newQuorum` MUST be greater than 0 and less than or equal to the number of members. +- Only the owner can call this function. +- Members MUST NOT be part of the set. +- `newQuorum` MUST be greater than 0 and less than or equal to the number of members. -### Function: HashConsensus.removeMembers +--- + +### Function: `HashConsensus.removeMembers` ```solidity function removeMembers(address[] memory membersToRemove, uint256 executionQuorum) @@ -1136,11 +2073,13 @@ Removes members and updates the quorum. #### Preconditions -* Only the owner can call this function. -* Members MUST be part of the set. -* `newQuorum` MUST be greater than 0 and less than or equal to the number of remaining members. +- Only the owner can call this function. +- Members MUST be part of the set. +- `newQuorum` MUST be greater than 0 and less than or equal to the number of remaining members. -### Function: HashConsensus.getMembers +--- +` +### Function: `HashConsensus.getMembers` ```solidity function getMembers() view returns (address[] memory) @@ -1148,7 +2087,9 @@ function getMembers() view returns (address[] memory) Returns the list of current members. -### Function: HashConsensus.isMember +--- + +### Function: `HashConsensus.isMember` ```solidity function isMember(address member) view returns (bool) @@ -1156,7 +2097,9 @@ function isMember(address member) view returns (bool) Returns if an address is a member. -### Function: HashConsensus.setTimelockDuration +--- + +### Function: `HashConsensus.setTimelockDuration` ```solidity function setTimelockDuration(uint256 newTimelock) @@ -1166,10 +2109,12 @@ Sets the timelock duration. #### Preconditions -* Only the owner can call this function. -* The new `timelock` value MUST not be equal to the current one +- Only the owner can call this function. +- The new `timelock` value MUST not be equal to the current one -### Function: HashConsensus.setQuorum +--- + +### Function: `HashConsensus.setQuorum` ```solidity function setQuorum(uint256 newQuorum) @@ -1179,15 +2124,18 @@ Sets the quorum required for decision execution. #### Preconditions -* Only the owner can call this function. -* `newQuorum` MUST be greater than 0, less than or equal to the number of members, and not equal to the current `quorum` value. +- Only the owner can call this function. +- `newQuorum` MUST be greater than 0, less than or equal to the number of members, and not equal to the current `quorum` value. +--- -## Contract: TiebreakerCoreCommittee.sol +## Contract: `TiebreakerCoreCommittee` `TiebreakerCoreCommittee` is a smart contract that extends the `HashConsensus` and `ProposalsList` contracts to manage the scheduling of proposals and the resuming of sealable contracts through a consensus-based mechanism. It interacts with a DualGovernance contract to execute decisions once consensus is reached. -### Function: TiebreakerCoreCommittee.scheduleProposal +--- + +### Function: `TiebreakerCoreCommittee.scheduleProposal` ```solidity function scheduleProposal(uint256 proposalId) @@ -1197,10 +2145,12 @@ Schedules a proposal for execution by voting on it and adding it to the proposal #### Preconditions -* MUST be called by a member. -* Proposal with the given id MUST be submitted into `EmergencyProtectedTimelock` +- MUST be called by a member. +- Proposal with the given id MUST be submitted into `EmergencyProtectedTimelock` -### Function: TiebreakerCoreCommittee.getScheduleProposalState +--- + +### Function: `TiebreakerCoreCommittee.getScheduleProposalState` ```solidity function getScheduleProposalState(uint256 proposalId) @@ -1210,7 +2160,9 @@ function getScheduleProposalState(uint256 proposalId) Returns the state of a scheduled proposal including support count, quorum, and execution status. -### Function: TiebreakerCoreCommittee.executeScheduleProposal +--- + +### Function: `TiebreakerCoreCommittee.executeScheduleProposal` ```solidity function executeScheduleProposal(uint256 proposalId) @@ -1220,9 +2172,11 @@ Executes a scheduled proposal by calling the `tiebreakerScheduleProposal` functi #### Preconditions -* Proposal MUST be scheduled for execution and passed the timelock duration. +- Proposal MUST be scheduled for execution and passed the timelock duration. -### Function: TiebreakerCoreCommittee.getSealableResumeNonce +--- + +### Function: `TiebreakerCoreCommittee.getSealableResumeNonce` ```solidity function getSealableResumeNonce(address sealable) view returns (uint256) @@ -1230,7 +2184,9 @@ function getSealableResumeNonce(address sealable) view returns (uint256) Returns the current nonce for resuming operations of a sealable contract. -### Function: TiebreakerCoreCommittee.sealableResume +--- + +### Function: `TiebreakerCoreCommittee.sealableResume` ```solidity function sealableResume(address sealable, uint256 nonce) @@ -1240,10 +2196,12 @@ Submits a request to resume operations of a sealable contract by voting on it an #### Preconditions -* MUST be called by a member. -* The provided nonce MUST match the current nonce of the sealable contract. +- MUST be called by a member. +- The provided nonce MUST match the current nonce of the sealable contract. -### Function: TiebreakerCoreCommittee.getSealableResumeState +--- + +### Function: `TiebreakerCoreCommittee.getSealableResumeState` ```solidity function getSealableResumeState(address sealable, uint256 nonce) @@ -1253,7 +2211,9 @@ function getSealableResumeState(address sealable, uint256 nonce) Returns the state of a sealable resume request including support count, quorum, and execution status. -### Function: TiebreakerCoreCommittee.executeSealableResume +--- + +### Function: `TiebreakerCoreCommittee.executeSealableResume` ```solidity function executeSealableResume(address sealable) @@ -1263,13 +2223,17 @@ Executes a sealable resume request by calling the `tiebreakerResumeSealable` fun #### Preconditions -* Resume request MUST have reached quorum and passed the timelock duration. +- Resume request MUST have reached quorum and passed the timelock duration. + +--- -## Contract: TiebreakerSubCommittee.sol +## Contract: `TiebreakerSubCommittee` `TiebreakerSubCommittee` is a smart contract that extends the functionalities of `HashConsensus` and `ProposalsList` to manage the scheduling of proposals and the resumption of sealable contracts through a consensus mechanism. It interacts with the `TiebreakerCoreCommittee` contract to execute decisions once consensus is reached. -### Function: TiebreakerSubCommittee.scheduleProposal +--- + +### Function: `TiebreakerSubCommittee.scheduleProposal` ```solidity function scheduleProposal(uint256 proposalId) @@ -1278,11 +2242,12 @@ function scheduleProposal(uint256 proposalId) Schedules a proposal for execution by voting on it and adding it to the proposal list. #### Preconditions -* MUST be called by a member. -* Proposal with the given id MUST be submitted into `EmergencyProtectedTimelock` +- MUST be called by a member. +- Proposal with the given id MUST be submitted into `EmergencyProtectedTimelock` +--- -### Function: TiebreakerSubCommittee.getScheduleProposalState +### Function: `TiebreakerSubCommittee.getScheduleProposalState` ```solidity function getScheduleProposalState(uint256 proposalId) @@ -1292,7 +2257,9 @@ function getScheduleProposalState(uint256 proposalId) Returns the state of a scheduled proposal including support count, quorum, and execution status. -### Function: TiebreakerSubCommittee.executeScheduleProposal +--- + +### Function: `TiebreakerSubCommittee.executeScheduleProposal` ```solidity function executeScheduleProposal(uint256 proposalId) @@ -1302,9 +2269,11 @@ Executes a scheduled proposal by calling the scheduleProposal function on the `T #### Preconditions -* Proposal MUST have reached quorum and passed the timelock duration. +- Proposal MUST have reached quorum and passed the timelock duration. + +--- -### Function: TiebreakerSubCommittee.sealableResume +### Function: `TiebreakerSubCommittee.sealableResume` ```solidity function sealableResume(address sealable) @@ -1314,7 +2283,9 @@ Submits a request to resume operations of a sealable contract by voting on it an #### Preconditions -* MUST be called by a member. +- MUST be called by a member. + +### Function: `TiebreakerSubCommittee.getSealableResumeState` ```solidity function getSealableResumeState(address sealable) @@ -1324,7 +2295,9 @@ function getSealableResumeState(address sealable) Returns the state of a sealable resume request including support count, quorum, and execution status. -### Function: TiebreakerSubCommittee.executeSealableResume +--- + +### Function: `TiebreakerSubCommittee.executeSealableResume` ```solidity function executeSealableResume(address sealable) external @@ -1334,8 +2307,9 @@ Executes a sealable resume request by calling the sealableResume function on the #### Preconditions -* Resume request MUST have reached quorum and passed the timelock duration. +- Resume request MUST have reached quorum and passed the timelock duration. +--- ## Upgrade flow description @@ -1351,4 +2325,4 @@ A typical proposal to update the dual governance system to a new version will li 2. Deploy a new instance of the `ImmutableDualGovernanceConfigProvider` contract if necessary. 3. Configure emergency protection settings in the `EmergencyProtectedTimelock` contract, including the address of the committee, the duration of emergency protection, and the duration of the emergency mode. -For more significant updates involving changes to the `EmergencyProtectedTimelock` or `Proposals` mechanics, new versions of both the `DualGovernance` and `EmergencyProtectedTimelock` contracts are deployed. While this adds more steps to maintain the proposal history, such as tracking old and new versions of the Timelocks, it also eliminates the need to migrate permissions or rights from executors. The `transferExecutorOwnership()` function of the `EmergencyProtectedTimelock` facilitates the assignment of executors to the newly deployed contract. +For more significant updates involving changes to the `EmergencyProtectedTimelock` or `Proposals` mechanics, new versions of both the `DualGovernance` and `EmergencyProtectedTimelock` contracts are deployed. While this adds more steps to maintain the proposal history, such as tracking old and new versions of the Timelocks, it also eliminates the need to migrate permissions or rights from executors. The `transferExecutorOwnership` function of the `EmergencyProtectedTimelock` facilitates the assignment of executors to the newly deployed contract. diff --git a/foundry.toml b/foundry.toml index 35c94313..027aa3fd 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,4 +1,5 @@ [profile.default] +evm_version = 'cancun' src = 'contracts' out = 'out' script = 'scripts' @@ -9,7 +10,8 @@ cache_path = 'cache_forge' no-match-path = 'test/kontrol/*' fs_permissions = [ { access = "read-write", path = "./deploy-config"}, - { access = "read", path = "./scripts/smoke-checks"}, + { access = "read-write", path = "./deploy-artifacts"}, + { access = "read", path = "./scripts/smoke-checks"} ] [profile.kprove] diff --git a/package-lock.json b/package-lock.json index 3b2554d8..fe66bf76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,38 +8,17 @@ "name": "lido-dual-governance", "version": "0.0.1", "license": "MIT", - "dependencies": { - "@openzeppelin/contracts": "5.0.1" - }, "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-foundry": "^1.1.1", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-toolbox": "^3.0.0", - "@nomicfoundation/hardhat-verify": "^1.0.0", - "chai": "^4.2.0", - "dotenv": "^16.3.1", - "ethers": "^6.4.0", - "hardhat": "^2.17.2", - "hardhat-gas-reporter": "^1.0.8", "husky": "^9.0.10", "lint-staged": "^15.2.2", "solhint": "^4.1.1", - "solhint-plugin-lido": "^0.0.4", - "solidity-coverage": "^0.8.4" + "solhint-plugin-lido": "^0.0.4" }, "engines": { "node": ">=20", "pnpm": ">=8" } }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", - "dev": true - }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -76,7672 +55,1209 @@ "node": ">=6.9.0" } }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", - "dev": true - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", - "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" + "engines": { + "node": ">=12.22.0" } }, - "node_modules/@chainsafe/ssz": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", - "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dev": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", "dev": true, - "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" }, "engines": { "node": ">=12" } }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", "dev": true, - "bin": { - "rlp": "bin/rlp" - }, "engines": { - "node": ">=14" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@ethereumjs/util": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", - "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dev": true, "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "ethereum-cryptography": "^2.0.0", - "micro-ftch": "^0.3.1" + "defer-to-connect": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=14.16" } }, - "node_modules/@ethereumjs/util/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "@noble/hashes": "1.3.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">= 16" + "node": ">=18" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", - "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", - "dev": true, - "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=8" } }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], "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" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", - "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", - "dev": true, + "color-convert": "^1.9.0" + }, "engines": { - "node": ">=14" + "node": ">=4" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/antlr4": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", "dev": true, - "peer": true, "engines": { - "node": ">=6.0.0" + "node": ">=16" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true, - "peer": true + "node_modules/antlr4ts": { + "version": "0.5.0-alpha.4", + "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", + "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", + "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=12.0.0" - } + "node_modules/ast-parents": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", + "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", + "dev": true }, - "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "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" - } - }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "1.3.2" + "fill-range": "^7.1.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=8" } }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=14.16" } }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@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" }, "engines": { - "node": ">= 8" + "node": ">=14.16" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz", - "integrity": "sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz", - "integrity": "sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-ethash": "3.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" + "node": ">=18" }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz", - "integrity": "sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.2", - "crc-32": "^1.2.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz", - "integrity": "sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "0.1.3" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz", - "integrity": "sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==", - "dev": true, - "dependencies": { - "@ethersproject/providers": "^5.7.1", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "node": ">=18" }, - "engines": { - "node": ">=14" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz", - "integrity": "sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==", + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "bin": { - "rlp": "bin/rlp" - }, + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz", - "integrity": "sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" - } - }, - "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz", - "integrity": "sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==", + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "0.1.3", - "readable-stream": "^3.6.0" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz", - "integrity": "sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==", + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { - "@chainsafe/ssz": "^0.9.2", - "@ethersproject/providers": "^5.7.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" + "color-name": "1.1.3" } }, - "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz", - "integrity": "sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==", + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true, - "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=14" - } + "license": "MIT" }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", - "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", - "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz", - "integrity": "sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==", + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { "node": ">=14" - } - }, - "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.3.tgz", - "integrity": "sha512-A40s7EAK4Acr8UP1Yudgi9GGD9Cca/K3LHt3DzmRIje14lBfHtg9atGQ7qK56vdPcTwKmeaGn30FzxMUfPGEMw==", - "dev": true, - "dependencies": { - "@types/chai-as-promised": "^7.1.3", - "chai-as-promised": "^7.1.1", - "deep-eql": "^4.0.1", - "ordinal": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" }, "peerDependencies": { - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "chai": "^4.2.0", - "ethers": "^6.1.0", - "hardhat": "^2.9.4" + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@nomicfoundation/hardhat-ethers": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz", - "integrity": "sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "lodash.isequal": "^4.5.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "peerDependencies": { - "ethers": "^6.1.0", - "hardhat": "^2.0.0" + "engines": { + "node": ">= 8" } }, - "node_modules/@nomicfoundation/hardhat-foundry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-foundry/-/hardhat-foundry-1.1.1.tgz", - "integrity": "sha512-cXGCBHAiXas9Pg9MhMOpBVQCkWRYoRFG7GJJAph+sdQsfd22iRs5U5Vs9XmpGEQd1yEvYISQZMeE68Nxj65iUQ==", + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "chalk": "^2.4.2" + "isexe": "^2.0.0" }, - "peerDependencies": { - "hardhat": "^2.17.2" + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.10.tgz", - "integrity": "sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==", + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "license": "MIT", "dependencies": { - "ethereumjs-util": "^7.1.4" + "ms": "^2.1.3" }, - "peerDependencies": { - "hardhat": "^2.9.5" + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz", - "integrity": "sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA==", - "dev": true, - "peerDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-verify": "^1.0.0", - "@typechain/ethers-v6": "^0.4.0", - "@typechain/hardhat": "^8.0.0", - "@types/chai": "^4.2.0", - "@types/mocha": ">=9.1.0", - "@types/node": ">=12.0.0", - "chai": "^4.2.0", - "ethers": "^6.4.0", - "hardhat": "^2.11.0", - "hardhat-gas-reporter": "^1.0.8", - "solidity-coverage": "^0.8.1", - "ts-node": ">=8.0.0", - "typechain": "^8.2.0", - "typescript": ">=4.5.0" - } - }, - "node_modules/@nomicfoundation/hardhat-verify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-1.1.1.tgz", - "integrity": "sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "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" + "mimic-response": "^3.1.0" }, - "peerDependencies": { - "hardhat": "^2.0.4" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", - "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", - "dev": true, "engines": { - "node": ">= 12" + "node": ">=10" }, - "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" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz", - "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz", - "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==", - "cpu": [ - "x64" - ], + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">= 10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz", - "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==", - "cpu": [ - "x64" - ], + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">= 10" + "node": ">=4.0.0" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz", - "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==", - "cpu": [ - "arm64" - ], + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz", - "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz", - "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==", - "cpu": [ - "x64" - ], + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">= 10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz", - "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==", - "cpu": [ - "x64" - ], + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "is-arrayish": "^0.2.1" } }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz", - "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==", - "cpu": [ - "arm64" - ], + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">= 10" + "node": ">=0.8.0" } }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz", - "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==", - "cpu": [ - "ia32" - ], + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } + "license": "MIT" }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz", - "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==", - "cpu": [ - "x64" - ], + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@openzeppelin/contracts": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.1.tgz", - "integrity": "sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w==" - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "dependencies": { - "graceful-fs": "4.2.10" + "node": ">=16" }, - "engines": { - "node": ">=12.22.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@scure/base": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", - "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", "dev": true, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">= 14.17" } }, - "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", - "dev": true, - "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "dev": true, - "dependencies": { - "@noble/hashes": "1.3.1" + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "engines": { - "node": ">= 16" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", "dev": true, "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "@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" + }, + "engines": { + "node": ">=14.16" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "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" - }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/@sentry/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, - "node_modules/@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, "dependencies": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" }, "engines": { - "node": ">=6" + "node": ">=10.19.0" } }, - "node_modules/@sentry/hub/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "dependencies": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, "engines": { - "node": ">=6" + "node": ">=16.17.0" } }, - "node_modules/@sentry/minimal/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "node_modules/husky": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", + "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", "dev": true, - "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" + "bin": { + "husky": "bin.mjs" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/@sentry/node/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } }, - "node_modules/@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "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" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@sentry/tracing/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/@sentry/utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@solidity-parser/parser": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", - "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" + "license": "MIT", + "engines": { + "node": ">=0.12.0" } }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.1" - }, "engines": { - "node": ">=14.16" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true, - "peer": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "peer": true + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "peer": true + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "peer": true - }, - "node_modules/@typechain/ethers-v6": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.4.3.tgz", - "integrity": "sha512-TrxBsyb4ryhaY9keP6RzhFCviWYApcLCIRMPyWaKp2cZZrfaM3QBoxXTnw/eO4+DAY3l+8O0brNW0WgeQeOiDA==", - "dev": true, - "peer": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "ethers": "6.x", - "typechain": "^8.3.1", - "typescript": ">=4.7.0" - } - }, - "node_modules/@typechain/hardhat": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-8.0.3.tgz", - "integrity": "sha512-MytSmJJn+gs7Mqrpt/gWkTCOpOQ6ZDfRrRT2gtZL0rfGe4QrU4x9ZdW15fFbVM/XTa+5EsKiOMYXhRABibNeng==", + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, "dependencies": { - "fs-extra": "^9.1.0" + "argparse": "^2.0.1" }, - "peerDependencies": { - "@typechain/ethers-v6": "^0.4.3", - "ethers": "^6.1.0", - "hardhat": "^2.9.9", - "typechain": "^8.3.1" - } - }, - "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", - "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", - "dev": true - }, - "node_modules/@types/chai-as-promised": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", - "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", - "dev": true, - "dependencies": { - "@types/chai": "*" - } - }, - "node_modules/@types/concat-stream": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", - "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/form-data": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", - "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", - "dev": true, - "peer": true - }, - "node_modules/@types/node": { - "version": "20.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", - "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "@types/node": "*" + "json-buffer": "3.0.1" } }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, - "peer": true - }, - "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", - "dev": true - }, - "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", "dev": true, "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, - "dependencies": { - "@types/node": "*" + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/abstract-level": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", - "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", + "node_modules/lint-staged": { + "version": "15.2.11", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", + "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", "dev": true, + "license": "MIT", "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.4.0", + "execa": "~8.0.1", + "lilconfig": "~3.1.3", + "listr2": "~8.2.5", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.6.1" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "peer": true, "bin": { - "acorn": "bin/acorn" + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", - "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.4.0" + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, "engines": { - "node": ">=0.3.0" + "node": ">=18.0.0" } }, - "node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, + "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "node": ">=18" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "optional": true, + "license": "MIT", "engines": { - "node": ">=0.4.2" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/antlr4": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", - "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "node": ">=18" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "peer": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-parents": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", - "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", - "dev": true - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, - "node_modules/bigint-crypto-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz", - "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "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" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cbor": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", - "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", - "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/chai": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.0.tgz", - "integrity": "sha512-x9cHNq1uvkCdU+5xTkNh5WtgD4e4yDFCsp9jVc7N7qVeKeftv3gO/ZrviX5d+3ZfxdYnZXZYujjRInu1RogU6A==", - "dev": true, - "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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, - "dependencies": { - "check-error": "^1.0.2" - }, - "peerDependencies": { - "chai": ">= 2.1.2 < 5" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "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" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/classic-level": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", - "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", - "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^4.0.2", - "chalk": "^2.4.2", - "table-layout": "^1.0.2", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "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" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "peer": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/difflib": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", - "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", - "dev": true, - "dependencies": { - "heap": ">= 0.2.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "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" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", - "dev": true, - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eth-gas-reporter": { - "version": "0.2.27", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", - "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", - "dev": true, - "dependencies": { - "@solidity-parser/parser": "^0.14.0", - "axios": "^1.5.1", - "cli-table3": "^0.5.0", - "colors": "1.4.0", - "ethereum-cryptography": "^1.0.3", - "ethers": "^5.7.2", - "fs-readdir-recursive": "^1.1.0", - "lodash": "^4.17.14", - "markdown-table": "^1.1.3", - "mocha": "^10.2.0", - "req-cwd": "^2.0.0", - "sha1": "^1.1.1", - "sync-request": "^6.0.0" - }, - "peerDependencies": { - "@codechecks/client": "^0.1.0" - }, - "peerDependenciesMeta": { - "@codechecks/client": { - "optional": true - } - } - }, - "node_modules/eth-gas-reporter/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/eth-gas-reporter/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "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" - } - }, - "node_modules/ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", - "dev": true, - "dependencies": { - "js-sha3": "^0.8.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "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" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "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" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethers": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.9.2.tgz", - "integrity": "sha512-YpkrtILnMQz5jSEsJQRTpduaGT/CXuLnUIuOYzHA0v/7c8IX91m2J48wSKjzGL5L9J/Us3tLoUdb+OwE3U+FFQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/ethers-io/" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@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" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true - }, - "node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "peer": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ghost-testrpc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", - "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "node-emoji": "^1.10.0" - }, - "bin": { - "testrpc-sc": "index.js" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hardhat": { - "version": "2.19.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.19.4.tgz", - "integrity": "sha512-fTQJpqSt3Xo9Mn/WrdblNGAfcANM6XC3tAEi6YogB4s02DmTf93A8QsGb8uR0KR8TFcpcS8lgiW4ugAIYpnbrQ==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@nomicfoundation/ethereumjs-vm": "7.0.2", - "@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", - "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" - }, - "bin": { - "hardhat": "internal/cli/bootstrap.js" - }, - "peerDependencies": { - "ts-node": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/hardhat-gas-reporter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", - "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", - "dev": true, - "dependencies": { - "array-uniq": "1.0.3", - "eth-gas-reporter": "^0.2.25", - "sha1": "^1.1.1" - }, - "peerDependencies": { - "hardhat": "^2.0.2" - } - }, - "node_modules/hardhat/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/hardhat/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/hardhat/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/hardhat/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/hardhat/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/hardhat/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/hardhat/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/heap": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http-basic": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", - "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", - "dev": true, - "dependencies": { - "caseless": "^0.12.0", - "concat-stream": "^1.6.2", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-response-object": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", - "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", - "dev": true, - "dependencies": { - "@types/node": "^10.0.3" - } - }, - "node_modules/http-response-object/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "dev": true - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/husky": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", - "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", - "dev": true, - "bin": { - "husky": "bin.mjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "dev": true, - "dependencies": { - "fp-ts": "^1.0.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-sdsl": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", - "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "peer": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/keccak": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", - "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, - "node_modules/latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", - "dev": true, - "dependencies": { - "package-json": "^8.1.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/level": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", - "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", - "dev": true, - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", - "dev": true, - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "peer": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", - "dev": true, - "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", - "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "peer": true - }, - "node_modules/markdown-table": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", - "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "dev": true, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micro-ftch": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", - "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "dev": true, - "dependencies": { - "obliterator": "^2.0.0" - } - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "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": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.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" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", - "dev": true, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordinal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", - "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", - "dev": true - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/package-json": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", - "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", - "dev": true, - "dependencies": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/package-json/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "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" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "dev": true, - "dependencies": { - "asap": "~2.0.6" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/registry-auth-token": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", - "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", - "dev": true, - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/req-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", - "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", - "dev": true, - "dependencies": { - "req-from": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/req-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", - "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", - "dev": true, - "dependencies": { - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dev": true, - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "dev": true - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", - "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "dev": true, - "dependencies": { - "bn.js": "^5.2.0" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sc-istanbul": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", - "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", - "dev": true, - "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" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/sc-istanbul/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/sc-istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/sc-istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sc-istanbul/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sc-istanbul/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true - }, - "node_modules/sc-istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", - "dev": true, - "dependencies": { - "charenc": ">= 0.0.1", - "crypt": ">= 0.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", - "dev": true, - "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" - }, - "bin": { - "solcjs": "solcjs" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/solhint": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-4.1.1.tgz", - "integrity": "sha512-7G4iF8H5hKHc0tR+/uyZesSKtfppFIMvPSW+Ku6MSL25oVRuyFeqNhOsXHfkex64wYJyXs4fe+pvhB069I19Tw==", - "dev": true, - "dependencies": { - "@solidity-parser/parser": "^0.16.0", - "ajv": "^6.12.6", - "antlr4": "^4.11.0", - "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" - }, - "bin": { - "solhint": "solhint.js" - }, - "optionalDependencies": { - "prettier": "^2.8.3" - } - }, - "node_modules/solhint-plugin-lido": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/solhint-plugin-lido/-/solhint-plugin-lido-0.0.4.tgz", - "integrity": "sha512-c+MsZY8zfVahIekswH04baEymE4foUS4oq62nKodUOEJ9mbkMACDszx7zevlAePW/77EBd2NONZdnRPy9WvpFQ==", - "dev": true - }, - "node_modules/solhint/node_modules/@solidity-parser/parser": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", - "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", - "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/solhint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "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" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/solhint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/solhint/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/solhint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/solhint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/solhint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/solhint/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/solhint/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/solhint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", "dev": true, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solhint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "node_modules/solhint/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=10" + "node": ">=8.6" } }, - "node_modules/solhint/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solhint/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, + "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">=18" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solhint/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", + "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solhint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solhint/node_modules/yallist": { + "node_modules/npm-run-path/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/solidity-coverage": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.5.tgz", - "integrity": "sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.16.0", - "chalk": "^2.4.2", - "death": "^1.1.0", - "detect-port": "^1.3.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.15", - "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" - }, - "bin": { - "solidity-coverage": "plugins/bin.js" + "engines": { + "node": ">=12" }, - "peerDependencies": { - "hardhat": "^2.11.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", - "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" + "wrappy": "1" } }, - "node_modules/solidity-coverage/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solidity-coverage/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=12.20" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dev": true, + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solidity-coverage/node_modules/lru-cache": { + "node_modules/package-json/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -7753,10 +1269,10 @@ "node": ">=10" } }, - "node_modules/solidity-coverage/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/package-json/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -7768,165 +1284,165 @@ "node": ">=10" } }, - "node_modules/solidity-coverage/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/solidity-coverage/node_modules/yallist": { + "node_modules/package-json/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "optional": true, "dependencies": { - "amdefine": ">=0.0.4" + "callsites": "^3.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=6" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@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" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "type-fest": "^0.7.1" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { - "node": ">=0.6.19" + "node": ">=6" } }, - "node_modules/string-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, - "peer": true + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "engines": { - "node": ">=4" + "bin": { + "rc": "cli.js" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "@pnpm/npm-conf": "^2.1.0" }, "engines": { - "node": ">=4" + "node": ">=14" } }, - "node_modules/strip-ansi": { + "node_modules/registry-url": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "rc": "1.2.8" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -7934,244 +1450,236 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, "engines": { - "node": ">=6.5.0", - "npm": ">=3" + "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, + "dependencies": { + "lowercase-keys": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sync-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", - "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "license": "MIT", "dependencies": { - "http-response-object": "^3.0.1", - "sync-rpc": "^1.2.1", - "then-request": "^6.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sync-rpc": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", - "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "dependencies": { - "get-port": "^3.1.0" - } + "license": "MIT" }, - "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "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" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=8" } }, - "node_modules/table-layout": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", - "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "peer": true, - "dependencies": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "peer": true, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, - "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/table/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8" + "node": ">=7.0.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/then-request": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", - "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "@types/concat-stream": "^1.6.0", - "@types/form-data": "0.0.33", - "@types/node": "^8.0.0", - "@types/qs": "^6.2.31", - "caseless": "~0.12.0", - "concat-stream": "^1.6.0", - "form-data": "^2.2.0", - "http-basic": "^8.1.1", - "http-response-object": "^3.0.1", - "promise": "^8.0.0", - "qs": "^6.4.0" - }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/then-request/node_modules/@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "dev": true - }, - "node_modules/then-request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "node_modules/solhint": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-4.1.1.tgz", + "integrity": "sha512-7G4iF8H5hKHc0tR+/uyZesSKtfppFIMvPSW+Ku6MSL25oVRuyFeqNhOsXHfkex64wYJyXs4fe+pvhB069I19Tw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "@solidity-parser/parser": "^0.16.0", + "ajv": "^6.12.6", + "antlr4": "^4.11.0", + "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" }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" + "bin": { + "solhint": "solhint.js" }, - "engines": { - "node": ">=0.6.0" + "optionalDependencies": { + "prettier": "^2.8.3" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } + "node_modules/solhint-plugin-lido": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/solhint-plugin-lido/-/solhint-plugin-lido-0.0.4.tgz", + "integrity": "sha512-c+MsZY8zfVahIekswH04baEymE4foUS4oq62nKodUOEJ9mbkMACDszx7zevlAePW/77EBd2NONZdnRPy9WvpFQ==", + "dev": true }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/solhint/node_modules/@solidity-parser/parser": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", + "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", "dev": true, - "engines": { - "node": ">=0.6" + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" } }, - "node_modules/ts-command-line-args": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", - "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "node_modules/solhint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "peer": true, "dependencies": { - "chalk": "^4.1.0", - "command-line-args": "^5.1.1", - "command-line-usage": "^6.1.0", - "string-format": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "bin": { - "write-markdown": "dist/write-markdown.js" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ts-command-line-args/node_modules/ansi-styles": { + "node_modules/solhint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -8182,12 +1690,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ts-command-line-args/node_modules/chalk": { + "node_modules/solhint/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/solhint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8199,12 +1715,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ts-command-line-args/node_modules/color-convert": { + "node_modules/solhint/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -8212,247 +1727,85 @@ "node": ">=7.0.0" } }, - "node_modules/ts-command-line-args/node_modules/color-name": { + "node_modules/solhint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "peer": true + "dev": true }, - "node_modules/ts-command-line-args/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/solhint/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, - "peer": true, "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/ts-command-line-args/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/solhint/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, - "peer": true, "dependencies": { - "has-flag": "^4.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "peer": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "peer": true, - "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" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "node": ">=12" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/solhint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "peer": true, "engines": { - "node": ">=0.3.1" + "node": ">=8" } }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, - "node_modules/tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", - "dev": true - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "node_modules/solhint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "node_modules/solhint/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "prelude-ls": "~1.1.2" + "yallist": "^4.0.0" }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typechain": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", - "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", - "dev": true, - "peer": true, - "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" - }, - "bin": { - "typechain": "dist/cli/cli.js" - }, - "peerDependencies": { - "typescript": ">=4.3.0" - } - }, - "node_modules/typechain/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" } }, - "node_modules/typechain/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "node_modules/solhint/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "peer": true, "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typechain/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/typechain/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" + "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" } }, - "node_modules/typechain/node_modules/prettier": { + "node_modules/solhint/node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, - "peer": true, + "optional": true, "bin": { "prettier": "bin-prettier.js" }, @@ -8463,296 +1816,155 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/typechain/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "node_modules/solhint/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "dependencies": { + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true, "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undici": { - "version": "5.28.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.2.tgz", - "integrity": "sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==", - "dev": true, - "dependencies": { - "@fastify/busboy": "^2.0.0" + "semver": "bin/semver.js" }, "engines": { - "node": ">=14.0" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node": ">=10" + } + }, + "node_modules/solhint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "punycode": "^2.1.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "node_modules/solhint/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=0.6.19" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "peer": true - }, - "node_modules/web3-utils": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.3.tgz", - "integrity": "sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ==", + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "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" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.3.1" + "node": ">=18" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/web3-utils/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 16" + "node": ">=12" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/web3-utils/node_modules/ethereum-cryptography": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", - "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, - "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" - } + "license": "MIT" }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "ansi-regex": "^6.0.1" }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "node_modules/wordwrapjs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", - "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "peer": true, "dependencies": { - "reduce-flatten": "^2.0.0", - "typical": "^5.2.0" + "ansi-regex": "^5.0.1" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=10.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -8761,7 +1973,7 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/string-width": { + "node_modules/table/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -8775,142 +1987,126 @@ "node": ">=8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=8.0" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, + "optional": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=10" + "node": ">=14.17" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "engines": { - "node": ">= 14" + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "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" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "node": ">=12" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, - "engines": { - "node": ">=10" + "license": "ISC", + "bin": { + "yaml": "bin.mjs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 14" } } } diff --git a/package.json b/package.json index f8eb831c..e08bbeb6 100644 --- a/package.json +++ b/package.json @@ -22,21 +22,9 @@ ] }, "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-foundry": "^1.1.1", - "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomicfoundation/hardhat-toolbox": "^3.0.0", - "@nomicfoundation/hardhat-verify": "^1.0.0", - "chai": "^4.2.0", - "dotenv": "^16.3.1", - "ethers": "^6.4.0", - "hardhat": "^2.17.2", - "hardhat-gas-reporter": "^1.0.8", "husky": "^9.0.10", "lint-staged": "^15.2.2", "solhint": "^4.1.1", - "solhint-plugin-lido": "^0.0.4", - "solidity-coverage": "^0.8.4" + "solhint-plugin-lido": "^0.0.4" } } diff --git a/scripts/deploy-timelocked-governance/ConfigProvider.sol b/scripts/deploy-timelocked-governance/ConfigProvider.sol deleted file mode 100644 index 41eba922..00000000 --- a/scripts/deploy-timelocked-governance/ConfigProvider.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -/* solhint-disable no-console, var-name-mixedcase */ - -import {console} from "forge-std/console.sol"; -import {Vm} from "forge-std/Vm.sol"; -import {ConfigFileReader} from "../deploy/config/ConfigFileReader.sol"; - -string constant CONFIG_FILES_DIR = "deploy-config"; - -contract TimelockedGovernanceConfigProvider { - struct DeployConfig { - address GOVERNANCE; - address TIMELOCK; - } - - using ConfigFileReader for ConfigFileReader.Context; - - // solhint-disable-next-line const-name-snakecase - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - error InvalidParameter(string parameter); - - string private _configFileName; - - constructor(string memory configFileName) { - _configFileName = configFileName; - } - - function loadAndValidate() external view returns (DeployConfig memory config) { - ConfigFileReader.Context memory configFile = _loadConfigFile(); - - config = _parse(configFile); - - _validateConfig(config); - _printConfig(configFile.content); - } - - function _parse(ConfigFileReader.Context memory configFile) internal pure returns (DeployConfig memory config) { - config = DeployConfig({ - GOVERNANCE: configFile.readAddress(".TIMELOCKED_GOVERNANCE.GOVERNANCE"), - TIMELOCK: configFile.readAddress(".TIMELOCKED_GOVERNANCE.TIMELOCK") - }); - } - - function _validateConfig(DeployConfig memory config) internal pure { - if (config.GOVERNANCE == address(0)) { - revert InvalidParameter("GOVERNANCE"); - } - if (config.TIMELOCK == address(0)) { - revert InvalidParameter("TIMELOCK"); - } - } - - function _printConfig(string memory configFile) internal pure { - console.log("================================================="); - console.log("Loaded valid config file:"); - console.log(configFile); - console.log("================================================="); - } - - function _loadConfigFile() internal view returns (ConfigFileReader.Context memory configFile) { - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/", CONFIG_FILES_DIR, "/", _configFileName); - configFile = ConfigFileReader.load(path); - } -} diff --git a/scripts/deploy-timelocked-governance/DeployTG.s.sol b/scripts/deploy-timelocked-governance/DeployTG.s.sol index 632785eb..d3c9bec0 100644 --- a/scripts/deploy-timelocked-governance/DeployTG.s.sol +++ b/scripts/deploy-timelocked-governance/DeployTG.s.sol @@ -5,45 +5,37 @@ pragma solidity 0.8.26; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {ITimelock} from "contracts/interfaces/ITimelock.sol"; import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; -import {TimelockedGovernanceConfigProvider} from "./ConfigProvider.sol"; -import {DGContractsDeployment} from "../deploy/ContractsDeployment.sol"; +import {TimelockedGovernanceDeployConfig} from "../utils/contracts-deployment.sol"; +import {DeployFiles} from "../utils/deploy-files.sol"; contract DeployTG is Script { + using TimelockedGovernanceDeployConfig for TimelockedGovernanceDeployConfig.Context; + error ChainIdMismatch(uint256 actual, uint256 expected); - TimelockedGovernanceConfigProvider.DeployConfig internal _config; - address internal _deployer; - TimelockedGovernanceConfigProvider internal _configProvider; - string internal _configFileName; + TimelockedGovernanceDeployConfig.Context internal _config; - constructor() { - _configFileName = _getConfigFileName(); + function run() public { + string memory configFileName = vm.envString("TIMELOCKED_GOVERNANCE_CONFIG_FILE_NAME"); + console.log("Loading config file: %s", configFileName); - _configProvider = new TimelockedGovernanceConfigProvider(_configFileName); - _config = _configProvider.loadAndValidate(); - } + TimelockedGovernanceDeployConfig.Context memory deployConfig = TimelockedGovernanceDeployConfig.load( + DeployFiles.resolveDeployConfig(configFileName), "timelocked_governance" + ); - function run() public { - _deployer = msg.sender; - vm.label(_deployer, "DEPLOYER"); + deployConfig.print(); + + address deployer = msg.sender; + vm.label(deployer, "DEPLOYER"); vm.startBroadcast(); TimelockedGovernance timelockedGovernance = - DGContractsDeployment.deployTimelockedGovernance(_config.GOVERNANCE, ITimelock(_config.TIMELOCK)); + new TimelockedGovernance(deployConfig.governance, deployConfig.timelock); vm.stopBroadcast(); console.log("TimelockedGovernance deployed successfully at", address(timelockedGovernance)); } - - function _getChainName() internal virtual returns (string memory) { - return vm.envString("CHAIN"); - } - - function _getConfigFileName() internal virtual returns (string memory) { - return vm.envString("TIMELOCKED_GOVERNANCE_CONFIG_FILE_NAME"); - } } diff --git a/scripts/deploy-timelocked-governance/tg-config-example.toml b/scripts/deploy-timelocked-governance/tg-config-example.toml index 41bbe950..32192b76 100644 --- a/scripts/deploy-timelocked-governance/tg-config-example.toml +++ b/scripts/deploy-timelocked-governance/tg-config-example.toml @@ -1,3 +1,3 @@ -[TIMELOCKED_GOVERNANCE] -GOVERNANCE="address" -TIMELOCK="address" +[timelocked_governance] +governance="address" +timelock="address" diff --git a/scripts/deploy/ContractsDeployment.sol b/scripts/deploy/ContractsDeployment.sol deleted file mode 100644 index eddf0c81..00000000 --- a/scripts/deploy/ContractsDeployment.sol +++ /dev/null @@ -1,348 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -// --- -// Contracts -// --- -import {Duration} from "contracts/types/Duration.sol"; - -import {Executor} from "contracts/Executor.sol"; -import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; - -import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; - -import {ResealManager} from "contracts/ResealManager.sol"; -import {DualGovernance} from "contracts/DualGovernance.sol"; -import { - DualGovernanceConfig, - IDualGovernanceConfigProvider, - ImmutableDualGovernanceConfigProvider -} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; - -import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; -import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; -import {ITimelock} from "contracts/interfaces/ITimelock.sol"; -import {IResealManager} from "contracts/interfaces/IResealManager.sol"; -import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; - -import {DeployedContracts} from "./DeployedContractsSet.sol"; -import {DeployConfig, LidoContracts, TIEBREAKER_SUB_COMMITTEES_COUNT} from "./config/Config.sol"; - -library DGContractsDeployment { - function deployDualGovernanceSetup( - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses, - address deployer - ) internal returns (DeployedContracts memory contracts) { - contracts = deployAdminExecutorAndTimelock(dgDeployConfig, deployer); - deployEmergencyProtectedTimelockContracts(lidoAddresses, dgDeployConfig, contracts); - contracts.resealManager = deployResealManager(contracts.timelock); - ImmutableDualGovernanceConfigProvider dualGovernanceConfigProvider = - deployDualGovernanceConfigProvider(dgDeployConfig); - DualGovernance dualGovernance = deployDualGovernance({ - configProvider: dualGovernanceConfigProvider, - timelock: contracts.timelock, - resealManager: contracts.resealManager, - dgDeployConfig: dgDeployConfig, - lidoAddresses: lidoAddresses - }); - contracts.dualGovernance = dualGovernance; - - contracts.tiebreakerCoreCommittee = deployEmptyTiebreakerCoreCommittee({ - owner: deployer, // temporary set owner to deployer, to add sub committees manually - dualGovernance: address(dualGovernance), - executionDelay: dgDeployConfig.tiebreakerConfig.executionDelay - }); - - (TiebreakerSubCommittee influencers, TiebreakerSubCommittee nodeOperators, TiebreakerSubCommittee protocols) = - deployTiebreakerSubCommittees( - address(contracts.adminExecutor), contracts.tiebreakerCoreCommittee, dgDeployConfig - ); - contracts.tiebreakerSubCommitteeInfluencers = influencers; - contracts.tiebreakerSubCommitteeNodeOperators = nodeOperators; - contracts.tiebreakerSubCommitteeProtocols = protocols; - - contracts.tiebreakerCoreCommittee.transferOwnership(address(contracts.adminExecutor)); - - // --- - // Finalize Setup - // --- - configureDualGovernance(dgDeployConfig, lidoAddresses, contracts); - - finalizeEmergencyProtectedTimelockDeploy(contracts.adminExecutor, contracts.timelock, address(dualGovernance)); - } - - function deployAdminExecutorAndTimelock( - DeployConfig memory dgDeployConfig, - address deployer - ) internal returns (DeployedContracts memory contracts) { - Executor adminExecutor = deployExecutor({owner: deployer}); - IEmergencyProtectedTimelock timelock = deployEmergencyProtectedTimelock(address(adminExecutor), dgDeployConfig); - - contracts.adminExecutor = adminExecutor; - contracts.timelock = timelock; - } - - function deployEmergencyProtectedTimelockContracts( - LidoContracts memory lidoAddresses, - DeployConfig memory dgDeployConfig, - DeployedContracts memory contracts - ) internal returns (TimelockedGovernance emergencyGovernance, TimelockedGovernance temporaryEmergencyGovernance) { - Executor adminExecutor = contracts.adminExecutor; - IEmergencyProtectedTimelock timelock = contracts.timelock; - - emergencyGovernance = deployTimelockedGovernance({governance: lidoAddresses.voting, timelock: timelock}); - contracts.emergencyGovernance = emergencyGovernance; - - adminExecutor.execute( - address(timelock), - 0, - abi.encodeCall( - timelock.setEmergencyProtectionActivationCommittee, (dgDeployConfig.EMERGENCY_ACTIVATION_COMMITTEE) - ) - ); - adminExecutor.execute( - address(timelock), - 0, - abi.encodeCall( - timelock.setEmergencyProtectionExecutionCommittee, (dgDeployConfig.EMERGENCY_EXECUTION_COMMITTEE) - ) - ); - - adminExecutor.execute( - address(timelock), - 0, - abi.encodeCall(timelock.setEmergencyProtectionEndDate, dgDeployConfig.EMERGENCY_PROTECTION_END_DATE) - ); - adminExecutor.execute( - address(timelock), - 0, - abi.encodeCall(timelock.setEmergencyModeDuration, (dgDeployConfig.EMERGENCY_MODE_DURATION)) - ); - - if (dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER != address(0)) { - temporaryEmergencyGovernance = deployTimelockedGovernance({ - governance: dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER, - timelock: timelock - }); - adminExecutor.execute( - address(timelock), - 0, - abi.encodeCall(timelock.setEmergencyGovernance, (address(temporaryEmergencyGovernance))) - ); - contracts.temporaryEmergencyGovernance = temporaryEmergencyGovernance; - } else { - adminExecutor.execute( - address(timelock), 0, abi.encodeCall(timelock.setEmergencyGovernance, (address(emergencyGovernance))) - ); - } - } - - function deployExecutor(address owner) internal returns (Executor) { - return new Executor(owner); - } - - function deployEmergencyProtectedTimelock( - address adminExecutor, - DeployConfig memory dgDeployConfig - ) internal returns (IEmergencyProtectedTimelock) { - return IEmergencyProtectedTimelock( - new EmergencyProtectedTimelock({ - adminExecutor: address(adminExecutor), - sanityCheckParams: EmergencyProtectedTimelock.SanityCheckParams({ - minExecutionDelay: dgDeployConfig.MIN_EXECUTION_DELAY, - maxAfterSubmitDelay: dgDeployConfig.MAX_AFTER_SUBMIT_DELAY, - maxAfterScheduleDelay: dgDeployConfig.MAX_AFTER_SCHEDULE_DELAY, - maxEmergencyModeDuration: dgDeployConfig.MAX_EMERGENCY_MODE_DURATION, - maxEmergencyProtectionDuration: dgDeployConfig.MAX_EMERGENCY_PROTECTION_DURATION - }), - afterSubmitDelay: dgDeployConfig.AFTER_SUBMIT_DELAY, - afterScheduleDelay: dgDeployConfig.AFTER_SCHEDULE_DELAY - }) - ); - } - - function deployTimelockedGovernance( - address governance, - ITimelock timelock - ) internal returns (TimelockedGovernance) { - return new TimelockedGovernance(governance, timelock); - } - - function deployResealManager(ITimelock timelock) internal returns (ResealManager) { - return new ResealManager(timelock); - } - - function deployDualGovernanceConfigProvider(DeployConfig memory dgDeployConfig) - internal - returns (ImmutableDualGovernanceConfigProvider) - { - return new ImmutableDualGovernanceConfigProvider( - DualGovernanceConfig.Context({ - firstSealRageQuitSupport: dgDeployConfig.FIRST_SEAL_RAGE_QUIT_SUPPORT, - secondSealRageQuitSupport: dgDeployConfig.SECOND_SEAL_RAGE_QUIT_SUPPORT, - // - minAssetsLockDuration: dgDeployConfig.MIN_ASSETS_LOCK_DURATION, - vetoSignallingMinDuration: dgDeployConfig.VETO_SIGNALLING_MIN_DURATION, - vetoSignallingMaxDuration: dgDeployConfig.VETO_SIGNALLING_MAX_DURATION, - // - vetoSignallingMinActiveDuration: dgDeployConfig.VETO_SIGNALLING_MIN_ACTIVE_DURATION, - vetoSignallingDeactivationMaxDuration: dgDeployConfig.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION, - vetoCooldownDuration: dgDeployConfig.VETO_COOLDOWN_DURATION, - // - rageQuitExtensionPeriodDuration: dgDeployConfig.RAGE_QUIT_EXTENSION_PERIOD_DURATION, - rageQuitEthWithdrawalsMinDelay: dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY, - rageQuitEthWithdrawalsMaxDelay: dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY, - rageQuitEthWithdrawalsDelayGrowth: dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH - }) - ); - } - - function deployDualGovernance( - IDualGovernanceConfigProvider configProvider, - ITimelock timelock, - IResealManager resealManager, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses - ) internal returns (DualGovernance) { - return new DualGovernance({ - components: DualGovernance.DualGovernanceComponents({ - timelock: timelock, - resealManager: resealManager, - configProvider: configProvider - }), - signallingTokens: DualGovernance.SignallingTokens({ - stETH: lidoAddresses.stETH, - wstETH: lidoAddresses.wstETH, - withdrawalQueue: lidoAddresses.withdrawalQueue - }), - sanityCheckParams: DualGovernance.SanityCheckParams({ - minWithdrawalsBatchSize: dgDeployConfig.MIN_WITHDRAWALS_BATCH_SIZE, - minTiebreakerActivationTimeout: dgDeployConfig.tiebreakerConfig.minActivationTimeout, - maxTiebreakerActivationTimeout: dgDeployConfig.tiebreakerConfig.maxActivationTimeout, - maxSealableWithdrawalBlockersCount: dgDeployConfig.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT, - maxMinAssetsLockDuration: dgDeployConfig.MAX_MIN_ASSETS_LOCK_DURATION - }) - }); - } - - function deployEmptyTiebreakerCoreCommittee( - address owner, - address dualGovernance, - Duration executionDelay - ) internal returns (TiebreakerCoreCommittee) { - return new TiebreakerCoreCommittee({owner: owner, dualGovernance: dualGovernance, timelock: executionDelay}); - } - - function deployTiebreakerSubCommittees( - address owner, - TiebreakerCoreCommittee tiebreakerCoreCommittee, - DeployConfig memory dgDeployConfig - ) - internal - returns ( - TiebreakerSubCommittee influencers, - TiebreakerSubCommittee nodeOperators, - TiebreakerSubCommittee protocols - ) - { - influencers = deployTiebreakerSubCommittee({ - owner: owner, - quorum: dgDeployConfig.tiebreakerConfig.influencers.quorum, - members: dgDeployConfig.tiebreakerConfig.influencers.members, - tiebreakerCoreCommittee: address(tiebreakerCoreCommittee) - }); - - nodeOperators = deployTiebreakerSubCommittee({ - owner: owner, - quorum: dgDeployConfig.tiebreakerConfig.nodeOperators.quorum, - members: dgDeployConfig.tiebreakerConfig.nodeOperators.members, - tiebreakerCoreCommittee: address(tiebreakerCoreCommittee) - }); - - protocols = deployTiebreakerSubCommittee({ - owner: owner, - quorum: dgDeployConfig.tiebreakerConfig.protocols.quorum, - members: dgDeployConfig.tiebreakerConfig.protocols.members, - tiebreakerCoreCommittee: address(tiebreakerCoreCommittee) - }); - - address[] memory coreCommitteeMembers = new address[](TIEBREAKER_SUB_COMMITTEES_COUNT); - coreCommitteeMembers[0] = address(influencers); - coreCommitteeMembers[1] = address(nodeOperators); - coreCommitteeMembers[2] = address(protocols); - - tiebreakerCoreCommittee.addMembers(coreCommitteeMembers, dgDeployConfig.tiebreakerConfig.quorum); - } - - function deployTiebreakerSubCommittee( - address owner, - uint256 quorum, - address[] memory members, - address tiebreakerCoreCommittee - ) internal returns (TiebreakerSubCommittee) { - return new TiebreakerSubCommittee({ - owner: owner, - executionQuorum: quorum, - committeeMembers: members, - tiebreakerCoreCommittee: tiebreakerCoreCommittee - }); - } - - function configureDualGovernance( - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses, - DeployedContracts memory contracts - ) internal { - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall( - contracts.dualGovernance.registerProposer, (lidoAddresses.voting, address(contracts.adminExecutor)) - ) - ); - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall(contracts.dualGovernance.setProposalsCanceller, address(lidoAddresses.voting)) - ); - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall( - contracts.dualGovernance.setTiebreakerActivationTimeout, - dgDeployConfig.tiebreakerConfig.activationTimeout - ) - ); - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall(contracts.dualGovernance.setTiebreakerCommittee, address(contracts.tiebreakerCoreCommittee)) - ); - - for (uint256 i = 0; i < dgDeployConfig.tiebreakerConfig.sealableWithdrawalBlockers.length; ++i) { - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall( - contracts.dualGovernance.addTiebreakerSealableWithdrawalBlocker, - dgDeployConfig.tiebreakerConfig.sealableWithdrawalBlockers[i] - ) - ); - } - contracts.adminExecutor.execute( - address(contracts.dualGovernance), - 0, - abi.encodeCall(contracts.dualGovernance.setResealCommittee, dgDeployConfig.RESEAL_COMMITTEE) - ); - } - - function finalizeEmergencyProtectedTimelockDeploy( - Executor adminExecutor, - IEmergencyProtectedTimelock timelock, - address dualGovernance - ) internal { - adminExecutor.execute(address(timelock), 0, abi.encodeCall(timelock.setGovernance, (dualGovernance))); - adminExecutor.transferOwnership(address(timelock)); - } -} diff --git a/scripts/deploy/DeployConfigurable.s.sol b/scripts/deploy/DeployConfigurable.s.sol index 0b17c872..e0f7e4e1 100644 --- a/scripts/deploy/DeployConfigurable.s.sol +++ b/scripts/deploy/DeployConfigurable.s.sol @@ -3,99 +3,68 @@ pragma solidity 0.8.26; /* solhint-disable no-console */ -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {Script} from "forge-std/Script.sol"; -import {stdJson} from "forge-std/StdJson.sol"; import {console} from "forge-std/console.sol"; -import {ISignallingEscrow} from "contracts/interfaces/ISignallingEscrow.sol"; -import {DeployConfig, LidoContracts} from "./config/Config.sol"; -import {CONFIG_FILES_DIR, DGDeployConfigProvider} from "./config/ConfigProvider.sol"; -import {DeployedContracts, DGContractsSet} from "./DeployedContractsSet.sol"; -import {DGContractsDeployment} from "./ContractsDeployment.sol"; -import {DeployVerification} from "./DeployVerification.sol"; -import {SerializedJson, SerializedJsonLib} from "../utils/SerializedJson.sol"; +import { + DGSetupDeployConfig, + DGSetupDeployArtifacts, + ContractsDeployment, + DGSetupDeployedContracts +} from "../utils/contracts-deployment.sol"; +import {DeployVerification} from "../utils/DeployVerification.sol"; + +import {DeployFiles} from "../utils/deploy-files.sol"; contract DeployConfigurable is Script { - using SerializedJsonLib for SerializedJson; + using DGSetupDeployConfig for DGSetupDeployConfig.Context; + using DGSetupDeployArtifacts for DGSetupDeployArtifacts.Context; + using DGSetupDeployedContracts for DGSetupDeployedContracts.Context; error ChainIdMismatch(uint256 actual, uint256 expected); - DeployConfig internal _config; - LidoContracts internal _lidoAddresses; - address internal _deployer; - DeployedContracts internal _contracts; - DGDeployConfigProvider internal _configProvider; - string internal _chainName; - string internal _configFileName; - - constructor() { - _chainName = _getChainName(); - _configFileName = _getConfigFileName(); - - _configProvider = new DGDeployConfigProvider(_configFileName); - _config = _configProvider.loadAndValidate(); - _lidoAddresses = _configProvider.getLidoAddresses(_chainName); - } - function run() public { - if (_lidoAddresses.chainId != block.chainid) { - revert ChainIdMismatch({actual: block.chainid, expected: _lidoAddresses.chainId}); + string memory configFileName = vm.envString("DEPLOY_CONFIG_FILE_NAME"); + + console.log("Loading config file: %s", configFileName); + DGSetupDeployConfig.Context memory deployConfig = + DGSetupDeployConfig.load({configFilePath: DeployFiles.resolveDeployConfig(configFileName)}); + + if (deployConfig.chainId != block.chainid) { + revert ChainIdMismatch({actual: block.chainid, expected: deployConfig.chainId}); } - _deployer = msg.sender; - vm.label(_deployer, "DEPLOYER"); + console.log("Loaded config file: "); + console.log(deployConfig.toJSON()); + + deployConfig.validate(); + + address deployer = msg.sender; + vm.label(deployer, "DEPLOYER"); + + console.log("Deployer account: %x", deployer); vm.startBroadcast(); - _contracts = DGContractsDeployment.deployDualGovernanceSetup(_config, _lidoAddresses, _deployer); + DGSetupDeployedContracts.Context memory deployedContracts = + ContractsDeployment.deployDGSetup(deployer, deployConfig); vm.stopBroadcast(); console.log("DG deployed successfully"); - DGContractsSet.print(_contracts); + deployedContracts.print(); + + DGSetupDeployArtifacts.Context memory deployArtifact = + DGSetupDeployArtifacts.Context({deployConfig: deployConfig, deployedContracts: deployedContracts}); console.log("Verifying deploy"); - DeployVerification.verify(_contracts, _config, _lidoAddresses, false); + DeployVerification.verify(deployArtifact); console.log(unicode"Verified ✅"); - SerializedJson memory deployArtifactJson = SerializedJsonLib.getInstance(); - deployArtifactJson = _serializeDeployedContracts(deployArtifactJson); - deployArtifactJson = _configProvider.serialize(_config, deployArtifactJson); - deployArtifactJson = _configProvider.serializeLidoAddresses(_chainName, _lidoAddresses, deployArtifactJson); - _saveDeployArtifact(deployArtifactJson.str); - } - - function _serializeDeployedContracts(SerializedJson memory json) internal returns (SerializedJson memory) { - SerializedJson memory addrsJson = DGContractsSet.serialize(_contracts); - addrsJson.set("DUAL_GOVERNANCE_CONFIG_PROVIDER", address(_contracts.dualGovernance.getConfigProvider())); - addrsJson.set( - "ESCROW_MASTER_COPY", - address(ISignallingEscrow(_contracts.dualGovernance.getVetoSignallingEscrow()).ESCROW_MASTER_COPY()) - ); - addrsJson.set("chainName", _chainName); - addrsJson.set("timestamp", block.timestamp); - - return json.set("DEPLOYED_CONTRACTS", addrsJson.str); - } - - function _saveDeployArtifact(string memory deployedAddrsJson) internal { - string memory addressesFileName = - string.concat("deploy-artifact-", _chainName, "-", Strings.toString(block.timestamp), ".json"); - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/", CONFIG_FILES_DIR, "/", addressesFileName); - - stdJson.write(deployedAddrsJson, path); - - console.log("The deployed contracts' addresses are saved to file", path); - } - - function _getChainName() internal virtual returns (string memory) { - return vm.envString("CHAIN"); - } + string memory deployArtifactFileName = + string.concat("deploy-artifact-", vm.toString(block.chainid), "-", vm.toString(block.timestamp)); - function _getConfigFileName() internal virtual returns (string memory) { - return vm.envString("DEPLOY_CONFIG_FILE_NAME"); + deployArtifact.save(string.concat(deployArtifactFileName, ".toml")); } } diff --git a/scripts/deploy/DeployHoleskyTestnet.s.sol b/scripts/deploy/DeployHoleskyTestnet.s.sol deleted file mode 100644 index 9f6abd67..00000000 --- a/scripts/deploy/DeployHoleskyTestnet.s.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {DeployConfigurable} from "./DeployConfigurable.s.sol"; - -contract DeployHoleskyTestnet is DeployConfigurable { - function _getChainName() internal pure override returns (string memory) { - return "holesky"; - } - - function _getConfigFileName() internal pure override returns (string memory) { - return "deploy-config-holesky-testnet.toml"; - } -} diff --git a/scripts/deploy/DeployedContractsSet.sol b/scripts/deploy/DeployedContractsSet.sol deleted file mode 100644 index a2bd9788..00000000 --- a/scripts/deploy/DeployedContractsSet.sol +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -/* solhint-disable no-console */ - -import {stdJson} from "forge-std/StdJson.sol"; -import {console} from "forge-std/console.sol"; -import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; -import {Executor} from "contracts/Executor.sol"; -import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; -import {ResealManager} from "contracts/ResealManager.sol"; -import {DualGovernance} from "contracts/DualGovernance.sol"; -import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; -import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; -import {SerializedJson, SerializedJsonLib} from "../utils/SerializedJson.sol"; - -struct DeployedContracts { - Executor adminExecutor; - IEmergencyProtectedTimelock timelock; - TimelockedGovernance emergencyGovernance; - ResealManager resealManager; - DualGovernance dualGovernance; - TiebreakerCoreCommittee tiebreakerCoreCommittee; - TiebreakerSubCommittee tiebreakerSubCommitteeInfluencers; - TiebreakerSubCommittee tiebreakerSubCommitteeNodeOperators; - TiebreakerSubCommittee tiebreakerSubCommitteeProtocols; - TimelockedGovernance temporaryEmergencyGovernance; -} - -library DGContractsSet { - using stdJson for string; - using SerializedJsonLib for SerializedJson; - - function print(DeployedContracts memory contracts) internal pure { - console.log("DualGovernance address", address(contracts.dualGovernance)); - console.log("ResealManager address", address(contracts.resealManager)); - console.log("TiebreakerCoreCommittee address", address(contracts.tiebreakerCoreCommittee)); - - console.log( - "TiebreakerSubCommittee - Influencers address", address(contracts.tiebreakerSubCommitteeInfluencers) - ); - console.log( - "TiebreakerSubCommittee - NodeOperators address", address(contracts.tiebreakerSubCommitteeNodeOperators) - ); - console.log("TiebreakerSubCommittee - Protocols address", address(contracts.tiebreakerSubCommitteeProtocols)); - - console.log("AdminExecutor address", address(contracts.adminExecutor)); - console.log("EmergencyProtectedTimelock address", address(contracts.timelock)); - console.log("EmergencyGovernance address", address(contracts.emergencyGovernance)); - console.log("TemporaryEmergencyGovernance address", address(contracts.temporaryEmergencyGovernance)); - } - - function loadFromFile(string memory file) internal pure returns (DeployedContracts memory) { - return DeployedContracts({ - adminExecutor: Executor(payable(file.readAddress(".DEPLOYED_CONTRACTS.ADMIN_EXECUTOR"))), - timelock: IEmergencyProtectedTimelock(file.readAddress(".DEPLOYED_CONTRACTS.TIMELOCK")), - emergencyGovernance: TimelockedGovernance(file.readAddress(".DEPLOYED_CONTRACTS.EMERGENCY_GOVERNANCE")), - resealManager: ResealManager(file.readAddress(".DEPLOYED_CONTRACTS.RESEAL_MANAGER")), - dualGovernance: DualGovernance(file.readAddress(".DEPLOYED_CONTRACTS.DUAL_GOVERNANCE")), - tiebreakerCoreCommittee: TiebreakerCoreCommittee( - file.readAddress(".DEPLOYED_CONTRACTS.TIEBREAKER_CORE_COMMITTEE") - ), - tiebreakerSubCommitteeInfluencers: TiebreakerSubCommittee( - file.readAddress(".DEPLOYED_CONTRACTS.TIEBREAKER_SUB_COMMITTEE_INFLUENCERS") - ), - tiebreakerSubCommitteeNodeOperators: TiebreakerSubCommittee( - file.readAddress(".DEPLOYED_CONTRACTS.TIEBREAKER_SUB_COMMITTEE_NODE_OPERATORS") - ), - tiebreakerSubCommitteeProtocols: TiebreakerSubCommittee( - file.readAddress(".DEPLOYED_CONTRACTS.TIEBREAKER_SUB_COMMITTEE_PROTOCOLS") - ), - temporaryEmergencyGovernance: TimelockedGovernance( - file.readAddress(".DEPLOYED_CONTRACTS.TEMPORARY_EMERGENCY_GOVERNANCE") - ) - }); - } - - function serialize(DeployedContracts memory contracts) internal returns (SerializedJson memory) { - SerializedJson memory addressesJson = SerializedJsonLib.getInstance(); - - addressesJson.set("ADMIN_EXECUTOR", address(contracts.adminExecutor)); - addressesJson.set("TIMELOCK", address(contracts.timelock)); - addressesJson.set("EMERGENCY_GOVERNANCE", address(contracts.emergencyGovernance)); - addressesJson.set("RESEAL_MANAGER", address(contracts.resealManager)); - addressesJson.set("DUAL_GOVERNANCE", address(contracts.dualGovernance)); - addressesJson.set("TIEBREAKER_CORE_COMMITTEE", address(contracts.tiebreakerCoreCommittee)); - addressesJson.set("TIEBREAKER_SUB_COMMITTEE_INFLUENCERS", address(contracts.tiebreakerSubCommitteeInfluencers)); - addressesJson.set( - "TIEBREAKER_SUB_COMMITTEE_NODE_OPERATORS", address(contracts.tiebreakerSubCommitteeNodeOperators) - ); - addressesJson.set("TIEBREAKER_SUB_COMMITTEE_PROTOCOLS", address(contracts.tiebreakerSubCommitteeProtocols)); - addressesJson.set("TEMPORARY_EMERGENCY_GOVERNANCE", address(contracts.temporaryEmergencyGovernance)); - - return addressesJson; - } -} diff --git a/scripts/deploy/Readme.md b/scripts/deploy/Readme.md index fb610b0e..ba4ec945 100644 --- a/scripts/deploy/Readme.md +++ b/scripts/deploy/Readme.md @@ -106,12 +106,12 @@ anvil --fork-url https://.infura.io/v3/ --bloc The Escrow contract is deployed internally by DualGovernance contract, so it can't be verified automatically during the initial deployment and requires manual verification afterward. To run Etherscan verification: - a. Query the deployed DualGovernance contract instance for ESCROW_MASTER_COPY address. + a. Search the deployed DualGovernance contract events for `EscrowMasterCopyDeployed` event with a single argument - ESCROW_MASTER_COPY address. b. Run Etherscan verification (for example on a Holesky testnet) ``` - forge verify-contract --chain holesky --verifier-url https://api-holesky.etherscan.io/api --watch --constructor-args $(cast abi-encode "Escrow(address,address,address,address,uint256)" ) contracts/Escrow.sol:Escrow + forge verify-contract --chain holesky --verifier-url https://api-holesky.etherscan.io/api --watch --constructor-args $(cast abi-encode "Escrow(address,address,address,address,uint256,uint32)" ) contracts/Escrow.sol:Escrow ``` ### Running the verification script diff --git a/scripts/deploy/Verify.s.sol b/scripts/deploy/Verify.s.sol index 286a7937..09d99681 100644 --- a/scripts/deploy/Verify.s.sol +++ b/scripts/deploy/Verify.s.sol @@ -6,44 +6,33 @@ pragma solidity 0.8.26; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {DeployConfig, LidoContracts} from "./config/Config.sol"; -import {CONFIG_FILES_DIR, DGDeployConfigProvider} from "./config/ConfigProvider.sol"; -import {DeployedContracts, DGContractsSet} from "./DeployedContractsSet.sol"; -import {DeployVerification} from "./DeployVerification.sol"; +import {DGSetupDeployArtifacts, DGSetupDeployedContracts} from "../utils/contracts-deployment.sol"; +import {DeployFiles} from "../utils/deploy-files.sol"; +import {DeployVerification} from "../utils/DeployVerification.sol"; contract Verify is Script { - DeployConfig internal _config; - LidoContracts internal _lidoAddresses; + using DGSetupDeployArtifacts for DGSetupDeployArtifacts.Context; + using DGSetupDeployedContracts for DGSetupDeployedContracts.Context; + + error InvalidChainId(uint256 actual, uint256 expected); function run() external { - string memory chainName = vm.envString("CHAIN"); string memory deployArtifactFileName = vm.envString("DEPLOY_ARTIFACT_FILE_NAME"); - bool onchainVotingCheck = vm.envBool("ONCHAIN_VOTING_CHECK_MODE"); - DGDeployConfigProvider configProvider = new DGDeployConfigProvider(deployArtifactFileName); - _config = configProvider.loadAndValidate(); - _lidoAddresses = configProvider.getLidoAddresses(chainName); + console.log("Loading config from artifact file: %s", deployArtifactFileName); - DeployedContracts memory contracts = - DGContractsSet.loadFromFile(_loadDeployArtifactFile(deployArtifactFileName)); + DGSetupDeployArtifacts.Context memory deployArtifact = DGSetupDeployArtifacts.load(deployArtifactFileName); + if (deployArtifact.deployConfig.chainId != block.chainid) { + revert InvalidChainId({actual: block.chainid, expected: deployArtifact.deployConfig.chainId}); + } console.log("Using the following DG contracts addresses (from file", deployArtifactFileName, "):"); - DGContractsSet.print(contracts); + deployArtifact.deployedContracts.print(); console.log("Verifying deploy"); - DeployVerification.verify(contracts, _config, _lidoAddresses, onchainVotingCheck); + DeployVerification.verify(deployArtifact); console.log(unicode"Verified ✅"); } - - function _loadDeployArtifactFile(string memory deployArtifactFileName) - internal - view - returns (string memory deployedAddressesJson) - { - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/", CONFIG_FILES_DIR, "/", deployArtifactFileName); - deployedAddressesJson = vm.readFile(path); - } } diff --git a/scripts/deploy/config-example.toml b/scripts/deploy/config-example.toml new file mode 100644 index 00000000..657404eb --- /dev/null +++ b/scripts/deploy/config-example.toml @@ -0,0 +1,77 @@ +chain_id = 17000 + +# ====================== +# DUAL GOVERNANCE CONFIG +# ====================== + +[dual_governance] +admin_proposer = "
" +reseal_committee = "
" +proposals_canceller = "
" +tiebreaker_activation_timeout = 900 +sealable_withdrawal_blockers = ["
"] + +[dual_governance.signalling_tokens] +st_eth = "
" +wst_eth = "
" +withdrawal_queue = "
" + +[dual_governance.sanity_check_params] +min_withdrawals_batch_size = 1 +max_tiebreaker_activation_timeout = 1800 +min_tiebreaker_activation_timeout = 300 +max_sealable_withdrawal_blockers_count = 255 +max_min_assets_lock_duration = 3600 + +[dual_governance_config_provider] +first_seal_rage_quit_support = 300 +second_seal_rage_quit_support = 1500 +min_assets_lock_duration = 300 +veto_signalling_min_duration = 300 +veto_signalling_min_active_duration = 300 +veto_signalling_max_duration = 1800 +veto_signalling_deactivation_max_duration = 1800 +veto_cooldown_duration = 900 +rage_quit_extension_period_duration = 900 +rage_quit_eth_withdrawals_min_delay = 300 +rage_quit_eth_withdrawals_max_delay = 1800 +rage_quit_eth_withdrawals_delay_growth = 1296000 + +# ====================== +# EMERGENCY PROTECTED TIMELOCK CONFIG +# ====================== + +[timelock] +after_submit_delay = 900 +after_schedule_delay = 900 + +[timelock.sanity_check_params] +min_execution_delay = 300 +max_after_submit_delay = 1800 +max_after_schedule_delay = 1800 +max_emergency_mode_duration = 86400 # 1 day +max_emergency_protection_duration = 31536000 # 1 year + +[timelock.emergency_protection] +emergency_mode_duration = 86400 # 1 day +emergency_protection_end_date = 1767225600 # Thu Jan 01 2026 00:00:00 GMT+0000 +emergency_governance_proposer = "
" +emergency_activation_committee = "
" +emergency_execution_committee = "
" + +# ====================== +# TIEBREAKER CONFIG +# ====================== + +[tiebreaker] +quorum = 1 +committees_count = 3 +execution_delay = 900 + +[[tiebreaker.committees]] +quorum = 1 +members = [
] + +[[tiebreaker.committees]] +quorum = 1 +members = [
] \ No newline at end of file diff --git a/scripts/deploy/config/Config.sol b/scripts/deploy/config/Config.sol deleted file mode 100644 index 7db29be3..00000000 --- a/scripts/deploy/config/Config.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -/* solhint-disable var-name-mixedcase */ - -import {IStETH} from "contracts/interfaces/IStETH.sol"; -import {IWstETH} from "contracts/interfaces/IWstETH.sol"; -import {IWithdrawalQueue} from "contracts/interfaces/IWithdrawalQueue.sol"; -import {Duration} from "contracts/types/Duration.sol"; -import {Timestamp} from "contracts/types/Timestamp.sol"; -import {PercentD16} from "contracts/types/PercentD16.sol"; - -bytes32 constant CHAIN_NAME_MAINNET_HASH = keccak256(bytes("mainnet")); -bytes32 constant CHAIN_NAME_HOLESKY_HASH = keccak256(bytes("holesky")); -bytes32 constant CHAIN_NAME_HOLESKY_MOCKS_HASH = keccak256(bytes("holesky-mocks")); -uint256 constant TIEBREAKER_SUB_COMMITTEES_COUNT = 3; - -struct TiebreakerSubCommitteeDeployConfig { - address[] members; - uint256 quorum; -} - -struct TiebreakerDeployConfig { - Duration activationTimeout; - Duration minActivationTimeout; - Duration maxActivationTimeout; - Duration executionDelay; - TiebreakerSubCommitteeDeployConfig influencers; - TiebreakerSubCommitteeDeployConfig nodeOperators; - TiebreakerSubCommitteeDeployConfig protocols; - uint256 quorum; - address[] sealableWithdrawalBlockers; -} - -struct DeployConfig { - Duration MIN_EXECUTION_DELAY; - Duration AFTER_SUBMIT_DELAY; - Duration MAX_AFTER_SUBMIT_DELAY; - Duration AFTER_SCHEDULE_DELAY; - Duration MAX_AFTER_SCHEDULE_DELAY; - Duration EMERGENCY_MODE_DURATION; - Duration MAX_EMERGENCY_MODE_DURATION; - Timestamp EMERGENCY_PROTECTION_END_DATE; - Duration MAX_EMERGENCY_PROTECTION_DURATION; - address EMERGENCY_ACTIVATION_COMMITTEE; - address EMERGENCY_EXECUTION_COMMITTEE; - address RESEAL_COMMITTEE; - uint256 MIN_WITHDRAWALS_BATCH_SIZE; - TiebreakerDeployConfig tiebreakerConfig; - uint256 MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT; - PercentD16 FIRST_SEAL_RAGE_QUIT_SUPPORT; - PercentD16 SECOND_SEAL_RAGE_QUIT_SUPPORT; - Duration MIN_ASSETS_LOCK_DURATION; - Duration MAX_MIN_ASSETS_LOCK_DURATION; - Duration VETO_SIGNALLING_MIN_DURATION; - Duration VETO_SIGNALLING_MAX_DURATION; - Duration VETO_SIGNALLING_MIN_ACTIVE_DURATION; - Duration VETO_SIGNALLING_DEACTIVATION_MAX_DURATION; - Duration VETO_COOLDOWN_DURATION; - Duration RAGE_QUIT_EXTENSION_PERIOD_DURATION; - Duration RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY; - Duration RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY; - Duration RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH; - address TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER; -} - -struct LidoContracts { - uint256 chainId; - IStETH stETH; - IWstETH wstETH; - IWithdrawalQueue withdrawalQueue; - address voting; -} diff --git a/scripts/deploy/config/ConfigFileReader.sol b/scripts/deploy/config/ConfigFileReader.sol deleted file mode 100644 index 9fcdfc64..00000000 --- a/scripts/deploy/config/ConfigFileReader.sol +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {Vm} from "forge-std/Vm.sol"; -import {stdJson} from "forge-std/stdJson.sol"; -import {stdToml} from "forge-std/StdToml.sol"; -import {Durations, Duration} from "contracts/types/Duration.sol"; -import {Timestamps, Timestamp} from "contracts/types/Timestamp.sol"; -import {PercentsD16, PercentD16} from "contracts/types/PercentD16.sol"; - -enum ConfigFormat { - JSON, - TOML -} - -library ConfigFileReader { - // solhint-disable-next-line const-name-snakecase - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - error InvalidConfigFormat(uint256 format); - - struct Context { - ConfigFormat format; - string content; - } - - function load(string memory path) internal view returns (Context memory ctx) { - ctx.format = getFileFormatByPath(path); - ctx.content = vm.readFile(path); - } - - function readUint(Context memory ctx, string memory key) internal pure returns (uint256) { - if (ctx.format == ConfigFormat.JSON) return stdJson.readUint(ctx.content, key); - if (ctx.format == ConfigFormat.TOML) return stdToml.readUint(ctx.content, key); - revert InvalidConfigFormat(uint256(ctx.format)); - } - - function readDuration(Context memory ctx, string memory key) internal pure returns (Duration) { - return Durations.from(readUint(ctx, key)); - } - - function readTimestamp(Context memory ctx, string memory key) internal pure returns (Timestamp) { - return Timestamps.from(readUint(ctx, key)); - } - - function readPercentD16BP(Context memory ctx, string memory key) internal pure returns (PercentD16) { - return PercentsD16.fromBasisPoints(readUint(ctx, key)); - } - - function readAddress(Context memory ctx, string memory key) internal pure returns (address) { - if (ctx.format == ConfigFormat.JSON) return stdJson.readAddress(ctx.content, key); - if (ctx.format == ConfigFormat.TOML) return stdToml.readAddress(ctx.content, key); - revert InvalidConfigFormat(uint256(ctx.format)); - } - - function readAddressArray(Context memory ctx, string memory key) internal pure returns (address[] memory) { - if (ctx.format == ConfigFormat.JSON) return stdJson.readAddressArray(ctx.content, key); - if (ctx.format == ConfigFormat.TOML) return stdToml.readAddressArray(ctx.content, key); - revert InvalidConfigFormat(uint256(ctx.format)); - } - - function getFileFormatByPath(string memory path) internal pure returns (ConfigFormat) { - // solhint-disable-next-line custom-errors - require(bytes(path).length > 0, "empty file path"); - - string[] memory pathSplit = vm.split(path, "."); - - string memory fileFormat = pathSplit[pathSplit.length - 1]; - bytes32 fileExtensionDigest = keccak256(bytes(vm.toLowercase(fileFormat))); - - if (fileExtensionDigest == keccak256(bytes("toml"))) { - return ConfigFormat.TOML; - } else if (fileExtensionDigest == keccak256(bytes("json"))) { - return ConfigFormat.JSON; - } - // solhint-disable-next-line custom-errors - revert(string.concat("Unsupported file format: ", fileFormat)); - } -} diff --git a/scripts/deploy/config/ConfigProvider.sol b/scripts/deploy/config/ConfigProvider.sol deleted file mode 100644 index b04fb4f2..00000000 --- a/scripts/deploy/config/ConfigProvider.sol +++ /dev/null @@ -1,387 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -/* solhint-disable no-console, var-name-mixedcase */ - -import {console} from "forge-std/console.sol"; -import {Vm} from "forge-std/Vm.sol"; -import {IStETH} from "contracts/interfaces/IStETH.sol"; -import {IWstETH} from "contracts/interfaces/IWstETH.sol"; -import {IWithdrawalQueue} from "contracts/interfaces/IWithdrawalQueue.sol"; -import { - ST_ETH as MAINNET_ST_ETH, - WST_ETH as MAINNET_WST_ETH, - WITHDRAWAL_QUEUE as MAINNET_WITHDRAWAL_QUEUE, - DAO_VOTING as MAINNET_DAO_VOTING -} from "addresses/mainnet-addresses.sol"; -import { - ST_ETH as HOLESKY_ST_ETH, - WST_ETH as HOLESKY_WST_ETH, - WITHDRAWAL_QUEUE as HOLESKY_WITHDRAWAL_QUEUE, - DAO_VOTING as HOLESKY_DAO_VOTING -} from "addresses/holesky-addresses.sol"; -import {SerializedJson, SerializedJsonLib} from "../../utils/SerializedJson.sol"; -import { - DeployConfig, - LidoContracts, - TiebreakerDeployConfig, - TiebreakerSubCommitteeDeployConfig, - CHAIN_NAME_MAINNET_HASH, - CHAIN_NAME_HOLESKY_HASH, - CHAIN_NAME_HOLESKY_MOCKS_HASH, - TIEBREAKER_SUB_COMMITTEES_COUNT -} from "./Config.sol"; -import {ConfigFileReader} from "./ConfigFileReader.sol"; - -string constant CONFIG_FILES_DIR = "deploy-config"; - -contract DGDeployConfigProvider { - using ConfigFileReader for ConfigFileReader.Context; - using SerializedJsonLib for SerializedJson; - - // solhint-disable-next-line const-name-snakecase - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - error InvalidQuorum(string committee, uint256 quorum); - error InvalidParameter(string parameter); - error InvalidChain(string chainName); - - string private _configFileName; - - constructor(string memory configFileName) { - _configFileName = configFileName; - } - - function loadAndValidate() external view returns (DeployConfig memory config) { - ConfigFileReader.Context memory configFile = _loadConfigFile(); - - config = _parse(configFile); - - _validateConfig(config); - _printConfigAndCommittees(config, configFile.content); - } - - function getLidoAddresses(string memory chainName) external view returns (LidoContracts memory) { - bytes32 chainNameHash = keccak256(bytes(chainName)); - if ( - chainNameHash != CHAIN_NAME_MAINNET_HASH && chainNameHash != CHAIN_NAME_HOLESKY_HASH - && chainNameHash != CHAIN_NAME_HOLESKY_MOCKS_HASH - ) { - revert InvalidChain(chainName); - } - - if (keccak256(bytes(chainName)) == CHAIN_NAME_MAINNET_HASH) { - return LidoContracts({ - chainId: 1, - stETH: IStETH(MAINNET_ST_ETH), - wstETH: IWstETH(MAINNET_WST_ETH), - withdrawalQueue: IWithdrawalQueue(MAINNET_WITHDRAWAL_QUEUE), - voting: MAINNET_DAO_VOTING - }); - } - - if (keccak256(bytes(chainName)) == CHAIN_NAME_HOLESKY_MOCKS_HASH) { - ConfigFileReader.Context memory configFile = _loadConfigFile(); - - return _getHoleskyMockLidoAddresses(configFile); - } - - return LidoContracts({ - chainId: 17000, - stETH: IStETH(HOLESKY_ST_ETH), - wstETH: IWstETH(HOLESKY_WST_ETH), - withdrawalQueue: IWithdrawalQueue(HOLESKY_WITHDRAWAL_QUEUE), - voting: HOLESKY_DAO_VOTING - }); - } - - function _parse(ConfigFileReader.Context memory configFile) internal pure returns (DeployConfig memory config) { - TiebreakerSubCommitteeDeployConfig memory influencersSubCommitteeConfig = TiebreakerSubCommitteeDeployConfig({ - members: configFile.readAddressArray(".TIEBREAKER_CONFIG.INFLUENCERS.MEMBERS"), - quorum: configFile.readUint(".TIEBREAKER_CONFIG.INFLUENCERS.QUORUM") - }); - - TiebreakerSubCommitteeDeployConfig memory nodeOperatorsSubCommitteeConfig = TiebreakerSubCommitteeDeployConfig({ - members: configFile.readAddressArray(".TIEBREAKER_CONFIG.NODE_OPERATORS.MEMBERS"), - quorum: configFile.readUint(".TIEBREAKER_CONFIG.NODE_OPERATORS.QUORUM") - }); - - TiebreakerSubCommitteeDeployConfig memory protocolsSubCommitteeConfig = TiebreakerSubCommitteeDeployConfig({ - members: configFile.readAddressArray(".TIEBREAKER_CONFIG.PROTOCOLS.MEMBERS"), - quorum: configFile.readUint(".TIEBREAKER_CONFIG.PROTOCOLS.QUORUM") - }); - - TiebreakerDeployConfig memory tiebreakerConfig = TiebreakerDeployConfig({ - activationTimeout: configFile.readDuration(".TIEBREAKER_CONFIG.ACTIVATION_TIMEOUT"), - minActivationTimeout: configFile.readDuration(".TIEBREAKER_CONFIG.MIN_ACTIVATION_TIMEOUT"), - maxActivationTimeout: configFile.readDuration(".TIEBREAKER_CONFIG.MAX_ACTIVATION_TIMEOUT"), - executionDelay: configFile.readDuration(".TIEBREAKER_CONFIG.EXECUTION_DELAY"), - influencers: influencersSubCommitteeConfig, - nodeOperators: nodeOperatorsSubCommitteeConfig, - protocols: protocolsSubCommitteeConfig, - quorum: configFile.readUint(".TIEBREAKER_CONFIG.QUORUM"), - sealableWithdrawalBlockers: configFile.readAddressArray(".TIEBREAKER_CONFIG.SEALABLE_WITHDRAWAL_BLOCKERS") - }); - - config = DeployConfig({ - // - // EMERGENCY_PROTECTED_TIMELOCK_CONFIG - // - MIN_EXECUTION_DELAY: configFile.readDuration(".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.MIN_EXECUTION_DELAY"), - AFTER_SUBMIT_DELAY: configFile.readDuration(".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.AFTER_SUBMIT_DELAY"), - MAX_AFTER_SUBMIT_DELAY: configFile.readDuration(".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.MAX_AFTER_SUBMIT_DELAY"), - AFTER_SCHEDULE_DELAY: configFile.readDuration(".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.AFTER_SCHEDULE_DELAY"), - MAX_AFTER_SCHEDULE_DELAY: configFile.readDuration( - ".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.MAX_AFTER_SCHEDULE_DELAY" - ), - EMERGENCY_MODE_DURATION: configFile.readDuration(".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.EMERGENCY_MODE_DURATION"), - MAX_EMERGENCY_MODE_DURATION: configFile.readDuration( - ".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.MAX_EMERGENCY_MODE_DURATION" - ), - EMERGENCY_PROTECTION_END_DATE: configFile.readTimestamp( - ".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.EMERGENCY_PROTECTION_END_DATE" - ), - MAX_EMERGENCY_PROTECTION_DURATION: configFile.readDuration( - ".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.MAX_EMERGENCY_PROTECTION_DURATION" - ), - TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER: configFile.readAddress( - ".EMERGENCY_PROTECTED_TIMELOCK_CONFIG.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER" - ), - // - // DUAL_GOVERNANCE_CONFIG - // - EMERGENCY_ACTIVATION_COMMITTEE: configFile.readAddress(".DUAL_GOVERNANCE_CONFIG.EMERGENCY_ACTIVATION_COMMITTEE"), - EMERGENCY_EXECUTION_COMMITTEE: configFile.readAddress(".DUAL_GOVERNANCE_CONFIG.EMERGENCY_EXECUTION_COMMITTEE"), - tiebreakerConfig: tiebreakerConfig, - RESEAL_COMMITTEE: configFile.readAddress(".DUAL_GOVERNANCE_CONFIG.RESEAL_COMMITTEE"), - MIN_WITHDRAWALS_BATCH_SIZE: configFile.readUint(".DUAL_GOVERNANCE_CONFIG.MIN_WITHDRAWALS_BATCH_SIZE"), - MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT: configFile.readUint( - ".DUAL_GOVERNANCE_CONFIG.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT" - ), - FIRST_SEAL_RAGE_QUIT_SUPPORT: configFile.readPercentD16BP( - ".DUAL_GOVERNANCE_CONFIG.FIRST_SEAL_RAGE_QUIT_SUPPORT" - ), - SECOND_SEAL_RAGE_QUIT_SUPPORT: configFile.readPercentD16BP( - ".DUAL_GOVERNANCE_CONFIG.SECOND_SEAL_RAGE_QUIT_SUPPORT" - ), - MIN_ASSETS_LOCK_DURATION: configFile.readDuration(".DUAL_GOVERNANCE_CONFIG.MIN_ASSETS_LOCK_DURATION"), - MAX_MIN_ASSETS_LOCK_DURATION: configFile.readDuration(".DUAL_GOVERNANCE_CONFIG.MAX_MIN_ASSETS_LOCK_DURATION"), - VETO_SIGNALLING_MIN_DURATION: configFile.readDuration(".DUAL_GOVERNANCE_CONFIG.VETO_SIGNALLING_MIN_DURATION"), - VETO_SIGNALLING_MAX_DURATION: configFile.readDuration(".DUAL_GOVERNANCE_CONFIG.VETO_SIGNALLING_MAX_DURATION"), - VETO_SIGNALLING_MIN_ACTIVE_DURATION: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.VETO_SIGNALLING_MIN_ACTIVE_DURATION" - ), - VETO_SIGNALLING_DEACTIVATION_MAX_DURATION: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION" - ), - VETO_COOLDOWN_DURATION: configFile.readDuration(".DUAL_GOVERNANCE_CONFIG.VETO_COOLDOWN_DURATION"), - RAGE_QUIT_EXTENSION_PERIOD_DURATION: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.RAGE_QUIT_EXTENSION_PERIOD_DURATION" - ), - RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY" - ), - RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY" - ), - RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH: configFile.readDuration( - ".DUAL_GOVERNANCE_CONFIG.RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH" - ) - }); - } - - function _getHoleskyMockLidoAddresses(ConfigFileReader.Context memory configFile) - internal - pure - returns (LidoContracts memory) - { - return LidoContracts({ - chainId: 17000, - stETH: IStETH(configFile.readAddress(".HOLESKY_MOCK_CONTRACTS.ST_ETH")), - wstETH: IWstETH(configFile.readAddress(".HOLESKY_MOCK_CONTRACTS.WST_ETH")), - withdrawalQueue: IWithdrawalQueue(configFile.readAddress(".HOLESKY_MOCK_CONTRACTS.WITHDRAWAL_QUEUE")), - voting: configFile.readAddress(".HOLESKY_MOCK_CONTRACTS.DAO_VOTING") - }); - } - - function _validateConfig(DeployConfig memory config) internal pure { - if (config.tiebreakerConfig.quorum == 0 || config.tiebreakerConfig.quorum > TIEBREAKER_SUB_COMMITTEES_COUNT) { - revert InvalidQuorum("TIEBREAKER_CORE", config.tiebreakerConfig.quorum); - } - - _checkCommitteeQuorum(config.tiebreakerConfig.influencers, "TIEBREAKER_CONFIG.INFLUENCERS"); - - _checkCommitteeQuorum(config.tiebreakerConfig.nodeOperators, "TIEBREAKER_CONFIG.NODE_OPERATORS"); - - _checkCommitteeQuorum(config.tiebreakerConfig.protocols, "TIEBREAKER_CONFIG.PROTOCOLS"); - - if (config.AFTER_SUBMIT_DELAY > config.MAX_AFTER_SUBMIT_DELAY) { - revert InvalidParameter("AFTER_SUBMIT_DELAY"); - } - - if (config.AFTER_SCHEDULE_DELAY > config.MAX_AFTER_SCHEDULE_DELAY) { - revert InvalidParameter("AFTER_SCHEDULE_DELAY"); - } - - if (config.EMERGENCY_MODE_DURATION > config.MAX_EMERGENCY_MODE_DURATION) { - revert InvalidParameter("EMERGENCY_MODE_DURATION"); - } - - if (config.tiebreakerConfig.minActivationTimeout > config.tiebreakerConfig.activationTimeout) { - revert InvalidParameter("TIEBREAKER_CONFIG.MIN_ACTIVATION_TIMEOUT"); - } - - if (config.tiebreakerConfig.activationTimeout > config.tiebreakerConfig.maxActivationTimeout) { - revert InvalidParameter("TIEBREAKER_CONFIG.ACTIVATION_TIMEOUT"); - } - - if (config.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT == 0) { - revert InvalidParameter("MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT"); - } - - if (config.tiebreakerConfig.sealableWithdrawalBlockers.length > config.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT) { - revert InvalidParameter("TIEBREAKER_CONFIG.SEALABLE_WITHDRAWAL_BLOCKERS"); - } - - if (config.VETO_SIGNALLING_MIN_DURATION > config.VETO_SIGNALLING_MAX_DURATION) { - revert InvalidParameter("VETO_SIGNALLING_MIN_DURATION"); - } - } - - function _checkCommitteeQuorum( - TiebreakerSubCommitteeDeployConfig memory committee, - string memory message - ) internal pure { - if (committee.quorum == 0 || committee.quorum > committee.members.length) { - revert InvalidQuorum(message, committee.quorum); - } - } - - function _printConfigAndCommittees(DeployConfig memory config, string memory configFile) internal pure { - console.log("================================================="); - console.log("Loaded valid config file:"); - console.log(configFile); - console.log("================================================="); - console.log("The Tiebreaker committee in the config consists of the following subcommittees:"); - - _printCommittee(config.tiebreakerConfig.influencers, "TiebreakerSubCommittee #1 (influencers) members, quorum"); - - _printCommittee( - config.tiebreakerConfig.nodeOperators, "TiebreakerSubCommittee #2 (nodeOperators) members, quorum" - ); - - _printCommittee(config.tiebreakerConfig.protocols, "TiebreakerSubCommittee #3 (protocols) members, quorum"); - - console.log("================================================="); - } - - function _printCommittee( - TiebreakerSubCommitteeDeployConfig memory committee, - string memory message - ) internal pure { - console.log(message, committee.quorum, "of", committee.members.length); - for (uint256 k = 0; k < committee.members.length; ++k) { - console.log(">> #", k, address(committee.members[k])); - } - } - - function _loadConfigFile() internal view returns (ConfigFileReader.Context memory configFile) { - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/", CONFIG_FILES_DIR, "/", _configFileName); - configFile = ConfigFileReader.load(path); - } - - function serialize( - DeployConfig memory config, - SerializedJson memory json - ) external returns (SerializedJson memory) { - SerializedJson memory emergencyProtectedTimelockConfig = SerializedJsonLib.getInstance(); - emergencyProtectedTimelockConfig.set("MIN_EXECUTION_DELAY", config.MIN_EXECUTION_DELAY); - emergencyProtectedTimelockConfig.set("AFTER_SUBMIT_DELAY", config.AFTER_SUBMIT_DELAY); - emergencyProtectedTimelockConfig.set("MAX_AFTER_SUBMIT_DELAY", config.MAX_AFTER_SUBMIT_DELAY); - emergencyProtectedTimelockConfig.set("AFTER_SCHEDULE_DELAY", config.AFTER_SCHEDULE_DELAY); - emergencyProtectedTimelockConfig.set("MAX_AFTER_SCHEDULE_DELAY", config.MAX_AFTER_SCHEDULE_DELAY); - emergencyProtectedTimelockConfig.set("EMERGENCY_MODE_DURATION", config.EMERGENCY_MODE_DURATION); - emergencyProtectedTimelockConfig.set("MAX_EMERGENCY_MODE_DURATION", config.MAX_EMERGENCY_MODE_DURATION); - emergencyProtectedTimelockConfig.set("EMERGENCY_PROTECTION_END_DATE", config.EMERGENCY_PROTECTION_END_DATE); - emergencyProtectedTimelockConfig.set( - "MAX_EMERGENCY_PROTECTION_DURATION", config.MAX_EMERGENCY_PROTECTION_DURATION - ); - emergencyProtectedTimelockConfig.set( - "TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER", config.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER - ); - json.set("EMERGENCY_PROTECTED_TIMELOCK_CONFIG", emergencyProtectedTimelockConfig.str); - - SerializedJson memory dualGovernanceConfig = SerializedJsonLib.getInstance(); - dualGovernanceConfig.set("EMERGENCY_ACTIVATION_COMMITTEE", config.EMERGENCY_ACTIVATION_COMMITTEE); - dualGovernanceConfig.set("EMERGENCY_EXECUTION_COMMITTEE", config.EMERGENCY_EXECUTION_COMMITTEE); - dualGovernanceConfig.set("RESEAL_COMMITTEE", config.RESEAL_COMMITTEE); - dualGovernanceConfig.set("MIN_WITHDRAWALS_BATCH_SIZE", config.MIN_WITHDRAWALS_BATCH_SIZE); - dualGovernanceConfig.set( - "MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT", config.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT - ); - dualGovernanceConfig.setPercentD16BP("FIRST_SEAL_RAGE_QUIT_SUPPORT", config.FIRST_SEAL_RAGE_QUIT_SUPPORT); - dualGovernanceConfig.setPercentD16BP("SECOND_SEAL_RAGE_QUIT_SUPPORT", config.SECOND_SEAL_RAGE_QUIT_SUPPORT); - dualGovernanceConfig.set("MIN_ASSETS_LOCK_DURATION", config.MIN_ASSETS_LOCK_DURATION); - dualGovernanceConfig.set("MAX_MIN_ASSETS_LOCK_DURATION", config.MAX_MIN_ASSETS_LOCK_DURATION); - dualGovernanceConfig.set("VETO_SIGNALLING_MIN_DURATION", config.VETO_SIGNALLING_MIN_DURATION); - dualGovernanceConfig.set("VETO_SIGNALLING_MAX_DURATION", config.VETO_SIGNALLING_MAX_DURATION); - dualGovernanceConfig.set("VETO_SIGNALLING_MIN_ACTIVE_DURATION", config.VETO_SIGNALLING_MIN_ACTIVE_DURATION); - dualGovernanceConfig.set( - "VETO_SIGNALLING_DEACTIVATION_MAX_DURATION", config.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION - ); - dualGovernanceConfig.set("VETO_COOLDOWN_DURATION", config.VETO_COOLDOWN_DURATION); - dualGovernanceConfig.set("RAGE_QUIT_EXTENSION_PERIOD_DURATION", config.RAGE_QUIT_EXTENSION_PERIOD_DURATION); - dualGovernanceConfig.set("RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY", config.RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY); - dualGovernanceConfig.set("RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY", config.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY); - dualGovernanceConfig.set( - "RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH", config.RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH - ); - json.set("DUAL_GOVERNANCE_CONFIG", dualGovernanceConfig.str); - - SerializedJson memory tiebreakerInfluencers = SerializedJsonLib.getInstance(); - tiebreakerInfluencers.set("MEMBERS", config.tiebreakerConfig.influencers.members); - tiebreakerInfluencers.set("QUORUM", config.tiebreakerConfig.influencers.quorum); - - SerializedJson memory tiebreakerNodeOperators = SerializedJsonLib.getInstance(); - tiebreakerNodeOperators.set("MEMBERS", config.tiebreakerConfig.nodeOperators.members); - tiebreakerNodeOperators.set("QUORUM", config.tiebreakerConfig.nodeOperators.quorum); - - SerializedJson memory tiebreakerProtocols = SerializedJsonLib.getInstance(); - tiebreakerProtocols.set("MEMBERS", config.tiebreakerConfig.protocols.members); - tiebreakerProtocols.set("QUORUM", config.tiebreakerConfig.protocols.quorum); - - SerializedJson memory tiebreakerConfig = SerializedJsonLib.getInstance(); - tiebreakerConfig.set("INFLUENCERS", tiebreakerInfluencers.str); - tiebreakerConfig.set("NODE_OPERATORS", tiebreakerNodeOperators.str); - tiebreakerConfig.set("PROTOCOLS", tiebreakerProtocols.str); - tiebreakerConfig.set("ACTIVATION_TIMEOUT", config.tiebreakerConfig.activationTimeout); - tiebreakerConfig.set("MIN_ACTIVATION_TIMEOUT", config.tiebreakerConfig.minActivationTimeout); - tiebreakerConfig.set("MAX_ACTIVATION_TIMEOUT", config.tiebreakerConfig.maxActivationTimeout); - tiebreakerConfig.set("EXECUTION_DELAY", config.tiebreakerConfig.executionDelay); - tiebreakerConfig.set("QUORUM", config.tiebreakerConfig.quorum); - tiebreakerConfig.set("SEALABLE_WITHDRAWAL_BLOCKERS", config.tiebreakerConfig.sealableWithdrawalBlockers); - - json.set("TIEBREAKER_CONFIG", tiebreakerConfig.str); - - return json; - } - - function serializeLidoAddresses( - string memory chainName, - LidoContracts memory lidoContracts, - SerializedJson memory json - ) external returns (SerializedJson memory) { - if (keccak256(bytes(chainName)) == CHAIN_NAME_HOLESKY_MOCKS_HASH) { - SerializedJson memory holeskyMocks = SerializedJsonLib.getInstance(); - - holeskyMocks.set("ST_ETH", address(lidoContracts.stETH)); - holeskyMocks.set("WST_ETH", address(lidoContracts.wstETH)); - holeskyMocks.set("WITHDRAWAL_QUEUE", address(lidoContracts.withdrawalQueue)); - holeskyMocks.set("DAO_VOTING", address(lidoContracts.voting)); - - json.set("HOLESKY_MOCK_CONTRACTS", holeskyMocks.str); - } - return json; - } -} diff --git a/scripts/launch/DeployDeployVerifier.s.sol b/scripts/launch/DeployDeployVerifier.s.sol deleted file mode 100644 index 8710d1a5..00000000 --- a/scripts/launch/DeployDeployVerifier.s.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -/* solhint-disable no-console */ - -import {console} from "forge-std/console.sol"; -import {DeployScriptBase} from "./DeployScriptBase.sol"; -import {DeployVerifier} from "./DeployVerifier.sol"; - -contract DeployDeployVerifier is DeployScriptBase { - function run() external { - vm.label(msg.sender, "DEPLOYER"); - - _loadEnv(); - - vm.startBroadcast(); - - DeployVerifier deployVerifier = new DeployVerifier(_config, _lidoAddresses); - - vm.stopBroadcast(); - - console.log("DeployVerifier address", address(deployVerifier)); - } -} diff --git a/scripts/launch/DeployScriptBase.sol b/scripts/launch/DeployScriptBase.sol index dd31de70..26e60f7e 100644 --- a/scripts/launch/DeployScriptBase.sol +++ b/scripts/launch/DeployScriptBase.sol @@ -6,38 +6,47 @@ pragma solidity 0.8.26; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {Duration} from "contracts/types/Duration.sol"; -import {DeployConfig, LidoContracts} from "../deploy/config/Config.sol"; -import {CONFIG_FILES_DIR, DGDeployConfigProvider} from "../deploy/config/ConfigProvider.sol"; -import {DeployedContracts, DGContractsSet} from "../deploy/DeployedContractsSet.sol"; -import {DeployVerifier} from "./DeployVerifier.sol"; +import { + DGSetupDeployArtifacts, DGSetupDeployedContracts, DGSetupDeployConfig +} from "../utils/contracts-deployment.sol"; +import {DeployFiles} from "../utils/deploy-files.sol"; import {ExternalCall} from "contracts/libraries/ExternalCalls.sol"; +import {Duration} from "contracts/types/Duration.sol"; +import {LidoUtils} from "test/utils/lido-utils.sol"; contract DeployScriptBase is Script { - DeployConfig internal _config; - LidoContracts internal _lidoAddresses; - DeployedContracts internal _dgContracts; - string internal _chainName; - string internal _deployArtifactFileName; - DeployVerifier internal _deployVerifier; + using DGSetupDeployArtifacts for DGSetupDeployArtifacts.Context; + using DGSetupDeployedContracts for DGSetupDeployedContracts.Context; + + error InvalidChainId(uint256 chainId); + + DGSetupDeployedContracts.Context internal _dgContracts; + LidoUtils.Context internal _lidoUtils; + + function _loadEnv() internal returns (DGSetupDeployArtifacts.Context memory _deployArtifact) { + string memory deployArtifactFileName = vm.envString("DEPLOY_ARTIFACT_FILE_NAME"); - function _loadEnv() internal { - _chainName = vm.envString("CHAIN"); - _deployArtifactFileName = vm.envString("DEPLOY_ARTIFACT_FILE_NAME"); + console.log("Loading config from artifact file: %s", deployArtifactFileName); - DGDeployConfigProvider configProvider = new DGDeployConfigProvider(_deployArtifactFileName); + _deployArtifact = DGSetupDeployArtifacts.load(deployArtifactFileName); - _config = configProvider.loadAndValidate(); - _lidoAddresses = configProvider.getLidoAddresses(_chainName); - _dgContracts = DGContractsSet.loadFromFile(_loadDeployedAddressesFile(_deployArtifactFileName)); + _dgContracts = _deployArtifact.deployedContracts; - console.log("Using the following DG contracts addresses (from file", _deployArtifactFileName, "):"); - console.log("====================================="); - DGContractsSet.print(_dgContracts); - console.log("====================================="); + if (_deployArtifact.deployConfig.chainId != block.chainid) { + revert InvalidChainId(_deployArtifact.deployConfig.chainId); + } + + if (_deployArtifact.deployConfig.chainId == 1) { + _lidoUtils = LidoUtils.mainnet(); + } else if (_deployArtifact.deployConfig.chainId == 17000) { + _lidoUtils = LidoUtils.holesky(); + } else { + revert InvalidChainId(_deployArtifact.deployConfig.chainId); + } - _deployVerifier = new DeployVerifier(_config, _lidoAddresses); + console.log("Using the following DG contracts addresses (from file", deployArtifactFileName, "):"); + _dgContracts.print(); } function _printExternalCalls(ExternalCall[] memory calls) internal pure { @@ -64,16 +73,6 @@ contract DeployScriptBase is Script { return string(str); } - function _loadDeployedAddressesFile(string memory deployedAddressesFileName) - internal - view - returns (string memory deployedAddressesJson) - { - string memory root = vm.projectRoot(); - string memory path = string.concat(root, "/", CONFIG_FILES_DIR, "/", deployedAddressesFileName); - deployedAddressesJson = vm.readFile(path); - } - function _encodeExternalCalls(ExternalCall[] memory calls) internal pure returns (bytes memory result) { result = abi.encodePacked(bytes4(uint32(1))); diff --git a/scripts/launch/DeployVerifier.sol b/scripts/launch/DeployVerifier.sol deleted file mode 100644 index e04abe5d..00000000 --- a/scripts/launch/DeployVerifier.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {DeployedContracts} from "../deploy/DeployedContractsSet.sol"; -import {DeployVerification} from "../deploy/DeployVerification.sol"; -import {DeployConfig, LidoContracts} from "../deploy/config/Config.sol"; - -contract DeployVerifier { - event Verified(); - - DeployConfig internal _config; - LidoContracts internal _lidoAddresses; - - constructor(DeployConfig memory config, LidoContracts memory lidoAddresses) { - _config = config; - _lidoAddresses = lidoAddresses; - } - - function verify(DeployedContracts memory dgContracts, bool onchainVotingCheck) external { - DeployVerification.checkContractsConfiguration(dgContracts, _config, _lidoAddresses, onchainVotingCheck); - - emit Verified(); - } - - function getConfig() external view returns (DeployConfig memory) { - return _config; - } - - function getLidoAddresses() external view returns (LidoContracts memory) { - return _lidoAddresses; - } -} diff --git a/scripts/launch/DualGovernanceSetup.s.sol b/scripts/launch/DualGovernanceSetup.s.sol index 396170b5..0f42d84e 100644 --- a/scripts/launch/DualGovernanceSetup.s.sol +++ b/scripts/launch/DualGovernanceSetup.s.sol @@ -3,83 +3,83 @@ pragma solidity 0.8.26; -import {DeployScriptBase} from "./DeployScriptBase.sol"; -import {ExternalCall} from "contracts/libraries/ExternalCalls.sol"; -import {ExternalCallHelpers} from "test/utils/executor-calls.sol"; -import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; -import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; +// import {DeployScriptBase} from "./DeployScriptBase.sol"; +// import {ExternalCall} from "contracts/libraries/ExternalCalls.sol"; +// import {ExternalCallHelpers} from "test/utils/executor-calls.sol"; +// import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; +// import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; -import {console} from "forge-std/console.sol"; +// import {console} from "forge-std/console.sol"; -contract DualGovernanceSetup is DeployScriptBase { - function run() external { - _loadEnv(); +// contract DualGovernanceSetup is DeployScriptBase { +// function run() external { +// _loadEnv(); - // Propose to set Governance, Activation Committee, Execution Committee, Emergency Mode End Date and Emergency Mode Duration - ExternalCall[] memory calls; - uint256 emergencyProtectionEndsAfter = _config.EMERGENCY_PROTECTION_END_DATE.toSeconds(); +// // Propose to set Governance, Activation Committee, Execution Committee, Emergency Mode End Date and Emergency Mode Duration +// ExternalCall[] memory calls; +// uint256 emergencyProtectionEndsAfter = _config.EMERGENCY_PROTECTION_END_DATE.toSeconds(); - calls = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setGovernance.selector, address(_dgContracts.dualGovernance) - ) - }), - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setEmergencyGovernance.selector, address(_dgContracts.emergencyGovernance) - ) - }), - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setEmergencyProtectionActivationCommittee.selector, - _config.EMERGENCY_ACTIVATION_COMMITTEE - ) - }), - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setEmergencyProtectionExecutionCommittee.selector, - _config.EMERGENCY_EXECUTION_COMMITTEE - ) - }), - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setEmergencyProtectionEndDate.selector, emergencyProtectionEndsAfter - ) - }), - ExternalCall({ - target: address(_dgContracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - IEmergencyProtectedTimelock.setEmergencyModeDuration.selector, _config.EMERGENCY_MODE_DURATION - ) - }) - ] - ); - console.log("Calls to set DG state:"); - _printExternalCalls(calls); +// calls = ExternalCallHelpers.create( +// [ +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setGovernance.selector, address(_dgContracts.dualGovernance) +// ) +// }), +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setEmergencyGovernance.selector, address(_dgContracts.emergencyGovernance) +// ) +// }), +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setEmergencyProtectionActivationCommittee.selector, +// _config.EMERGENCY_ACTIVATION_COMMITTEE +// ) +// }), +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setEmergencyProtectionExecutionCommittee.selector, +// _config.EMERGENCY_EXECUTION_COMMITTEE +// ) +// }), +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setEmergencyProtectionEndDate.selector, emergencyProtectionEndsAfter +// ) +// }), +// ExternalCall({ +// target: address(_dgContracts.timelock), +// value: 0, +// payload: abi.encodeWithSelector( +// IEmergencyProtectedTimelock.setEmergencyModeDuration.selector, _config.EMERGENCY_MODE_DURATION +// ) +// }) +// ] +// ); +// console.log("Calls to set DG state:"); +// _printExternalCalls(calls); - console.log("Calls encoded:"); - console.logBytes(abi.encode(calls)); +// console.log("Calls encoded:"); +// console.logBytes(abi.encode(calls)); - console.log("Encoded \"submitProposal\":"); - console.logBytes( - abi.encodeWithSelector( - TimelockedGovernance.submitProposal.selector, - calls, - "Reset emergency mode and set original DG as governance" - ) - ); - } -} +// console.log("Encoded \"submitProposal\":"); +// console.logBytes( +// abi.encodeWithSelector( +// TimelockedGovernance.submitProposal.selector, +// calls, +// "Reset emergency mode and set original DG as governance" +// ) +// ); +// } +// } diff --git a/scripts/launch/HoleskyDryRunDAOVotingCalldataProvider.sol b/scripts/launch/HoleskyDryRunDAOVotingCalldataProvider.sol new file mode 100644 index 00000000..02d57ffe --- /dev/null +++ b/scripts/launch/HoleskyDryRunDAOVotingCalldataProvider.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +library HoleskyDryRunDAOVotingCalldataProvider { + function votingCalldata() public pure returns (bytes memory) { + return + hex"00000001da7d2573df555002503f29aa4003e398d28cc00f00000a44f4b00513000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006fc00000001fd1e42595cec3e83239bf8dfc535250e7f48e0bc000000649d0effdb000000000000000000000000da7d2573df555002503f29aa4003e398d28cc00f0000000000000000000000003f1c547b21f65e10480de3ad8e19faac46c95034a42eee1333c0758ba72be38e728b6dadb32ea767de5b4ddbaea1dae85b1b051ffd1e42595cec3e83239bf8dfc535250e7f48e0bc000000640a8ed3db000000000000000000000000e92329ec7ddb11d25e25b3c21eebf11f15eb325d0000000000000000000000003f1c547b21f65e10480de3ad8e19faac46c95034a42eee1333c0758ba72be38e728b6dadb32ea767de5b4ddbaea1dae85b1b051ffd1e42595cec3e83239bf8dfc535250e7f48e0bc00000064afd925df000000000000000000000000e92329ec7ddb11d25e25b3c21eebf11f15eb325d0000000000000000000000003f1c547b21f65e10480de3ad8e19faac46c95034a42eee1333c0758ba72be38e728b6dadb32ea767de5b4ddbaea1dae85b1b051fe92329ec7ddb11d25e25b3c21eebf11f15eb325d000000a4d948d4680000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000001c7cc160b58f8bb0bac94b80847e2cf2800565c50000000442f2ff15d139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d000000000000000000000000c2764655e3fe0bd2d3c710d74fa5a89162099fd8e92329ec7ddb11d25e25b3c21eebf11f15eb325d000000a4d948d4680000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000001c7cc160b58f8bb0bac94b80847e2cf2800565c50000000442f2ff15d2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7000000000000000000000000c2764655e3fe0bd2d3c710d74fa5a89162099fd8e92329ec7ddb11d25e25b3c21eebf11f15eb325d000000a4d948d4680000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000001091c0ec8b4d54a9fcb36269b5d5e5af43309e666000000442f2ff15d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da7d2573df555002503f29aa4003e398d28cc00f091c0ec8b4d54a9fcb36269b5d5e5af43309e66600000044d547741f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e92329ec7ddb11d25e25b3c21eebf11f15eb325dfd1e42595cec3e83239bf8dfc535250e7f48e0bc000000640a8ed3db000000000000000000000000d5ee9991f44b36e186a658dc2a0357eccf11b69b000000000000000000000000e92329ec7ddb11d25e25b3c21eebf11f15eb325db421f7ad7646747f3051c50c0b8e2377839296cd4973e27f63821d73e390338f0f8826a574bcfdc4997939076f6d82877971feb300000044221e2efc000000000000000000000000d5ee9991f44b36e186a658dc2a0357eccf11b69b000000000000000000000000c2764655e3fe0bd2d3c710d74fa5a89162099fd8b291a7f092d5cce0a3c93ea21bda3431129db2020000020453e51f8b000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000e92329ec7ddb11d25e25b3c21eebf11f15eb325d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c4d948d4680000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000007c00000001c3fc22c7e0d20247b797fb6dc743bd3879217c8100000004febb0f7e3db5aba48123bb8789f6f09ec714e7082bc267470000004491f0004c00000000000000000000000000000000000000000000000000000000000070800000000000000000000000000000000000000000000000000000000000011940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002804f6d6e6962757320766f74653a205265766f6b65207065726d697373696f6e20666f72205354414b494e475f434f4e54524f4c5f524f4c452066726f6d20566f74696e6720636f6e74726163742e3b0a204772616e74207065726d697373696f6e20666f72205354414b494e475f434f4e54524f4c5f524f4c4520746f204167656e7420636f6e74726163742e3b0a204368616e6765207065726d697373696f6e206d616e6167657220666f72204c69646f205354414b494e475f434f4e54524f4c5f524f4c452e3b0a204772616e74205769746864726177616c51756575652050415553455f524f4c4520746f2052657365616c204d616e616765722e3b0a204772616e74205769746864726177616c517565756520524553554d455f524f4c4520746f2052657365616c204d616e616765722e3b0a204772616e7420416c6c6f776564546f6b656e7352656769737472792044454641554c545f41444d494e5f524f4c4520746f20566f74696e672e3b0a205265766f6b6520416c6c6f776564546f6b656e7352656769737472792044454641554c545f41444d494e5f524f4c452066726f6d204167656e742e3b0a204772616e74207065726d697373696f6e20666f722052554e5f5343524950545f524f4c4520746f204447204578656375746f7220636f6e74726163742e3b0a2056616c6964617465207472616e7366657272656420726f6c65733b0a205375626d6974206669727374206475616c20676f7665726e616e63652070726f706f73616c2e0a6c69646f766f7465697066733a2f2f6261666b7265696634786b6e786d787364706e766d7662726e667573716f696c766466326f666c6f686375637774623261767279767736697a6561"; + } +} diff --git a/scripts/launch/LaunchAcceptance.s.sol b/scripts/launch/LaunchAcceptance.s.sol index 07d34e05..a40ff262 100644 --- a/scripts/launch/LaunchAcceptance.s.sol +++ b/scripts/launch/LaunchAcceptance.s.sol @@ -18,19 +18,25 @@ import {IAragonACL} from "test/utils/interfaces/IAragonACL.sol"; import {IAragonAgent} from "test/utils/interfaces/IAragonAgent.sol"; import {IGovernance} from "contracts/interfaces/IDualGovernance.sol"; -import {DeployVerifier} from "./DeployVerifier.sol"; +import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; -import {WITHDRAWAL_QUEUE, DAO_AGENT, DAO_VOTING, DAO_ACL} from "addresses/mainnet-addresses.sol"; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; +import {DeployVerification} from "../utils/DeployVerification.sol"; + +import {DGSetupDeployArtifacts, DGSetupDeployConfig} from "../utils/contracts-deployment.sol"; + +import {HoleskyDryRunDAOVotingCalldataProvider} from "./HoleskyDryRunDAOVotingCalldataProvider.sol"; + contract LaunchAcceptance is DeployScriptBase { using LidoUtils for LidoUtils.Context; - LidoUtils.Context internal lidoUtils = LidoUtils.mainnet(); - function run() external { - _loadEnv(); + address daoEmergencyGovernance = 0x3B20930B143F21C4a837a837cBBcd15ac0B93504; + + DGSetupDeployArtifacts.Context memory _deployArtifact = _loadEnv(); + DGSetupDeployConfig.Context memory _config = _deployArtifact.deployConfig; uint256 fromStep = vm.envUint("FROM_STEP"); require(fromStep < 10, "Invalid value of env variable FROM_STEP, should not exceed 10"); @@ -39,11 +45,9 @@ contract LaunchAcceptance is DeployScriptBase { IEmergencyProtectedTimelock timelock = _dgContracts.timelock; uint256 proposalId = 1; - RolesVerifier _rolesVerifier; if (fromStep == 0) { - // Verify deployment of all contracts before proceeding - _deployVerifier.verify(_dgContracts, false); + DeployVerification.verify(_deployArtifact); } else { console.log("STEP 0 SKIPPED - All contracts are deployed"); } @@ -51,7 +55,7 @@ contract LaunchAcceptance is DeployScriptBase { if (fromStep <= 1) { console.log("STEP 1 - Activate Emergency Mode"); // Activate Dual Governance Emergency Mode - vm.prank(_config.EMERGENCY_ACTIVATION_COMMITTEE); + vm.prank(_config.timelock.emergencyActivationCommittee); timelock.activateEmergencyMode(); console.log("Emergency mode activated"); @@ -65,7 +69,7 @@ contract LaunchAcceptance is DeployScriptBase { require(timelock.isEmergencyModeActive() == true, "Emergency mode is not active"); // Emergency Committee execute emergencyReset() - vm.prank(_config.EMERGENCY_EXECUTION_COMMITTEE); + vm.prank(_config.timelock.emergencyExecutionCommittee); timelock.emergencyReset(); console.log("Emergency mode reset"); @@ -76,14 +80,14 @@ contract LaunchAcceptance is DeployScriptBase { if (fromStep <= 3) { console.log("STEP 3 - Set DG state"); require( - timelock.getGovernance() == address(_dgContracts.temporaryEmergencyGovernance), + timelock.getGovernance() == address(_dgContracts.emergencyGovernance), "Incorrect governance address in EmergencyProtectedTimelock" ); require(timelock.isEmergencyModeActive() == false, "Emergency mode is active"); // Propose to set Governance, Activation Committee, Execution Committee, Emergency Mode End Date and Emergency Mode Duration ExternalCall[] memory calls; - uint256 emergencyProtectionEndsAfter = _config.EMERGENCY_PROTECTION_END_DATE.toSeconds(); + calls = ExternalCallHelpers.create( [ ExternalCall({ @@ -94,36 +98,37 @@ contract LaunchAcceptance is DeployScriptBase { ExternalCall({ target: address(timelock), value: 0, - payload: abi.encodeWithSelector( - timelock.setEmergencyGovernance.selector, address(_dgContracts.emergencyGovernance) - ) + payload: abi.encodeWithSelector(timelock.setEmergencyGovernance.selector, daoEmergencyGovernance) }), ExternalCall({ target: address(timelock), value: 0, payload: abi.encodeWithSelector( - timelock.setEmergencyProtectionActivationCommittee.selector, _config.EMERGENCY_ACTIVATION_COMMITTEE + timelock.setEmergencyProtectionActivationCommittee.selector, + _config.timelock.emergencyActivationCommittee ) }), ExternalCall({ target: address(timelock), value: 0, payload: abi.encodeWithSelector( - timelock.setEmergencyProtectionExecutionCommittee.selector, _config.EMERGENCY_EXECUTION_COMMITTEE + timelock.setEmergencyProtectionExecutionCommittee.selector, + _config.timelock.emergencyExecutionCommittee ) }), ExternalCall({ target: address(timelock), value: 0, payload: abi.encodeWithSelector( - timelock.setEmergencyProtectionEndDate.selector, emergencyProtectionEndsAfter + timelock.setEmergencyProtectionEndDate.selector, + _config.timelock.emergencyProtectionEndDate.toSeconds() ) }), ExternalCall({ target: address(timelock), value: 0, payload: abi.encodeWithSelector( - timelock.setEmergencyModeDuration.selector, _config.EMERGENCY_MODE_DURATION + timelock.setEmergencyModeDuration.selector, _config.timelock.emergencyModeDuration.toSeconds() ) }) ] @@ -146,8 +151,8 @@ contract LaunchAcceptance is DeployScriptBase { ); } - vm.prank(_config.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER); - proposalId = _dgContracts.temporaryEmergencyGovernance.submitProposal( + vm.prank(_config.timelock.emergencyGovernanceProposer); + proposalId = _dgContracts.emergencyGovernance.submitProposal( calls, "Reset emergency mode and set original DG as governance" ); @@ -161,12 +166,16 @@ contract LaunchAcceptance is DeployScriptBase { if (fromStep <= 4) { console.log("STEP 4 - Execute proposal"); // Schedule and execute the proposal - vm.warp(block.timestamp + _config.AFTER_SUBMIT_DELAY.toSeconds()); - _dgContracts.temporaryEmergencyGovernance.scheduleProposal(proposalId); - vm.warp(block.timestamp + _config.AFTER_SCHEDULE_DELAY.toSeconds()); + vm.warp(block.timestamp + _config.timelock.afterSubmitDelay.toSeconds()); + _dgContracts.emergencyGovernance.scheduleProposal(proposalId); + vm.warp(block.timestamp + _config.timelock.afterScheduleDelay.toSeconds()); timelock.execute(proposalId); + _dgContracts.emergencyGovernance = TimelockedGovernance(daoEmergencyGovernance); + console.log("Proposal executed"); + + console.log("Emergency Governance set to", address(_dgContracts.emergencyGovernance)); } else { console.log("STEP 4 SKIPPED - Proposal to set DG state already executed"); } @@ -184,28 +193,23 @@ contract LaunchAcceptance is DeployScriptBase { ); require(timelock.isEmergencyModeActive() == false, "Emergency mode is not active"); require( - timelock.getEmergencyActivationCommittee() == _config.EMERGENCY_ACTIVATION_COMMITTEE, + timelock.getEmergencyActivationCommittee() == _config.timelock.emergencyActivationCommittee, "Incorrect emergencyActivationCommittee address in EmergencyProtectedTimelock" ); require( - timelock.getEmergencyExecutionCommittee() == _config.EMERGENCY_EXECUTION_COMMITTEE, + timelock.getEmergencyExecutionCommittee() == _config.timelock.emergencyExecutionCommittee, "Incorrect emergencyExecutionCommittee address in EmergencyProtectedTimelock" ); IEmergencyProtectedTimelock.EmergencyProtectionDetails memory details = timelock.getEmergencyProtectionDetails(); require( - details.emergencyModeDuration == _config.EMERGENCY_MODE_DURATION, + details.emergencyModeDuration == _config.timelock.emergencyModeDuration, "Incorrect emergencyModeDuration in EmergencyProtectedTimelock" ); require( - details.emergencyProtectionEndsAfter == _config.EMERGENCY_PROTECTION_END_DATE, + details.emergencyProtectionEndsAfter == _config.timelock.emergencyProtectionEndDate, "Incorrect emergencyProtectionEndsAfter in EmergencyProtectedTimelock" ); - - // Activate Dual Governance with DAO Voting - - // Verify deployment - _deployVerifier.verify(_dgContracts, true); } else { console.log("STEP 5 SKIPPED - DG state already verified"); } @@ -213,137 +217,18 @@ contract LaunchAcceptance is DeployScriptBase { if (fromStep <= 6) { console.log("STEP 6 - Submitting DAO Voting proposal to activate Dual Governance"); - // Prepare RolesVerifier - // TODO: Sync with the actual voting script roles checker - address[] memory ozContracts = new address[](1); - RolesVerifier.OZRoleInfo[] memory roles = new RolesVerifier.OZRoleInfo[](2); - address[] memory pauseRoleHolders = new address[](2); - pauseRoleHolders[0] = address(0x79243345eDbe01A7E42EDfF5900156700d22611c); - pauseRoleHolders[1] = address(_dgContracts.resealManager); - address[] memory resumeRoleHolders = new address[](1); - resumeRoleHolders[0] = address(_dgContracts.resealManager); - - ozContracts[0] = address(_lidoAddresses.withdrawalQueue); - - roles[0] = RolesVerifier.OZRoleInfo({ - role: _lidoAddresses.withdrawalQueue.PAUSE_ROLE(), - accounts: pauseRoleHolders - }); - roles[1] = RolesVerifier.OZRoleInfo({ - role: _lidoAddresses.withdrawalQueue.RESUME_ROLE(), - accounts: resumeRoleHolders - }); - - _rolesVerifier = new RolesVerifier(ozContracts, roles); - - // DAO Voting to activate Dual Governance - // Prepare calls to execute by Agent - ExternalCall[] memory roleGrantingCalls; - roleGrantingCalls = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(_lidoAddresses.withdrawalQueue), - value: 0, - payload: abi.encodeWithSelector( - IAccessControl.grantRole.selector, - IWithdrawalQueue(WITHDRAWAL_QUEUE).PAUSE_ROLE(), - address(_dgContracts.resealManager) - ) - }), - ExternalCall({ - target: address(_lidoAddresses.withdrawalQueue), - value: 0, - payload: abi.encodeWithSelector( - IAccessControl.grantRole.selector, - IWithdrawalQueue(WITHDRAWAL_QUEUE).RESUME_ROLE(), - address(_dgContracts.resealManager) - ) - }), - ExternalCall({ - target: address(DAO_ACL), - value: 0, - payload: abi.encodeWithSelector( - IAragonACL.grantPermission.selector, - address(_dgContracts.adminExecutor), - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ) - }) - ] - ); - - // Propose to revoke Agent forward permission from Voting - ExternalCall[] memory revokeAgentForwardCall; - revokeAgentForwardCall = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(DAO_ACL), - value: 0, - payload: abi.encodeWithSelector( - IAragonACL.revokePermission.selector, - DAO_VOTING, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ) - }) - ] - ); - - ExternalCall[] memory revokeAgentForwardCallDualGovernanceProposal; - revokeAgentForwardCallDualGovernanceProposal = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(lidoUtils.agent), - value: 0, - payload: abi.encodeWithSelector( - IAragonForwarder.forward.selector, _encodeExternalCalls(revokeAgentForwardCall) - ) - }) - ] - ); - - // Prepare calls to execute Voting - bytes memory setPermissionPayload = abi.encodeWithSelector( - IAragonACL.setPermissionManager.selector, - DAO_AGENT, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ); - - bytes memory forwardRolePayload = - abi.encodeWithSelector(IAragonForwarder.forward.selector, _encodeExternalCalls(roleGrantingCalls)); - - bytes memory verifyPayload = abi.encodeWithSelector(DeployVerifier.verify.selector, _dgContracts, true); - - bytes memory verifyOZRolesPayload = abi.encodeWithSelector(RolesVerifier.verifyOZRoles.selector); - - bytes memory submitProposalPayload = abi.encodeWithSelector( - IGovernance.submitProposal.selector, - revokeAgentForwardCallDualGovernanceProposal, - "Revoke Agent forward permission from Voting" - ); - - ExternalCall[] memory activateCalls = ExternalCallHelpers.create( - [ - ExternalCall({target: address(DAO_ACL), value: 0, payload: setPermissionPayload}), - ExternalCall({target: address(DAO_AGENT), value: 0, payload: forwardRolePayload}), - ExternalCall({target: address(_deployVerifier), value: 0, payload: verifyPayload}), - // TODO: set real RolesVerifier contract address - // ExternalCall({target: address(_rolesVerifier), value: 0, payload: verifyOZRolesPayload}), - ExternalCall({target: address(_dgContracts.dualGovernance), value: 0, payload: submitProposalPayload}) - ] - ); - uint256 voteId = lidoUtils.adoptVote("Dual Governance activation vote", _encodeExternalCalls(activateCalls)); + bytes memory _encodedDAOVotingCalls = HoleskyDryRunDAOVotingCalldataProvider.votingCalldata(); + uint256 voteId = _lidoUtils.adoptVotePreparedBytecode(_encodedDAOVotingCalls); console.log("Vote ID", voteId); } else { console.log("STEP 6 SKIPPED - Dual Governance activation vote already submitted"); } if (fromStep <= 7) { - uint256 voteId = 0; + uint256 voteId = 503; require(voteId != 0); console.log("STEP 7 - Enacting DAO Voting proposal to activate Dual Governance"); - lidoUtils.executeVote(voteId); + _lidoUtils.executeVote(voteId); } else { console.log("STEP 7 SKIPPED - Dual Governance activation vote already executed"); } @@ -354,9 +239,9 @@ contract LaunchAcceptance is DeployScriptBase { uint256 expectedProposalId = 2; // Schedule and execute the proposal - _wait(_config.AFTER_SUBMIT_DELAY); + _wait(_config.timelock.afterSubmitDelay); _dgContracts.dualGovernance.scheduleProposal(expectedProposalId); - _wait(_config.AFTER_SCHEDULE_DELAY); + _wait(_config.timelock.afterScheduleDelay); timelock.execute(expectedProposalId); } else { console.log("STEP 8 SKIPPED - Dual Governance proposal already executed"); @@ -369,62 +254,23 @@ contract LaunchAcceptance is DeployScriptBase { someAgentForwardCall = ExternalCallHelpers.create( [ ExternalCall({ - target: address(DAO_ACL), + target: address(_lidoUtils.acl), value: 0, payload: abi.encodeWithSelector( IAragonACL.revokePermission.selector, address(_dgContracts.adminExecutor), - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() + _lidoUtils.agent, + IAragonAgent(_lidoUtils.agent).RUN_SCRIPT_ROLE() ) }) ] ); - vm.expectRevert("AGENT_CAN_NOT_FORWARD"); - vm.prank(DAO_VOTING); - IAragonForwarder(DAO_AGENT).forward(_encodeExternalCalls(someAgentForwardCall)); + vm.expectRevert("ACL_AUTH_NO_MANAGER"); + vm.prank(address(_lidoUtils.voting)); + IAragonForwarder(_lidoUtils.agent).forward(_encodeExternalCalls(someAgentForwardCall)); } else { console.log("STEP 9 SKIPPED - Agent forward permission already revoked"); } } } - -contract RolesVerifier { - struct OZRoleInfo { - bytes32 role; - address[] accounts; - } - - mapping(address => OZRoleInfo[]) public ozContractRoles; - address[] private _ozContracts; - - constructor(address[] memory ozContracts, OZRoleInfo[] memory roles) { - _ozContracts = ozContracts; - - for (uint256 i = 0; i < ozContracts.length; ++i) { - for (uint256 r = 0; r < roles.length; ++r) { - ozContractRoles[ozContracts[i]].push(); - uint256 lastIndex = ozContractRoles[ozContracts[i]].length - 1; - ozContractRoles[ozContracts[i]][lastIndex].role = roles[r].role; - address[] memory accounts = roles[r].accounts; - for (uint256 a = 0; a < accounts.length; ++a) { - ozContractRoles[ozContracts[i]][lastIndex].accounts.push(accounts[a]); - } - } - } - } - - function verifyOZRoles() external view { - for (uint256 i = 0; i < _ozContracts.length; ++i) { - OZRoleInfo[] storage roles = ozContractRoles[_ozContracts[i]]; - for (uint256 j = 0; j < roles.length; ++j) { - AccessControlEnumerable accessControl = AccessControlEnumerable(_ozContracts[i]); - assert(accessControl.getRoleMemberCount(roles[j].role) == roles[j].accounts.length); - for (uint256 k = 0; k < roles[j].accounts.length; ++k) { - assert(accessControl.hasRole(roles[j].role, roles[j].accounts[k]) == true); - } - } - } - } -} diff --git a/scripts/lido-mocks/StETHMock.sol b/scripts/lido-mocks/StETHMock.sol index fca91ae9..18e5870b 100644 --- a/scripts/lido-mocks/StETHMock.sol +++ b/scripts/lido-mocks/StETHMock.sol @@ -18,6 +18,10 @@ contract StETHMock is StETHBase { return "MStETH"; } + function getCurrentStakeLimit() external pure returns (uint256) { + return type(uint256).max; + } + function rebaseTotalPooledEther(PercentD16 rebaseFactor) public { _totalPooledEther = rebaseFactor.toUint256() * _totalPooledEther / HUNDRED_PERCENT_D16; } @@ -27,12 +31,7 @@ contract StETHMock is StETHBase { } function mint(address account, uint256 ethAmount) external { - uint256 sharesAmount = getSharesByPooledEth(ethAmount); - - _mintShares(account, sharesAmount); - _totalPooledEther += ethAmount; - - _emitTransferAfterMintingShares(account, sharesAmount); + _mint(account, ethAmount); } function burn(address account, uint256 ethAmount) external { @@ -41,4 +40,21 @@ contract StETHMock is StETHBase { _totalPooledEther -= ethAmount; _emitTransferEvents(account, address(0), ethAmount, sharesToBurn); } + + function submit(address /* _referral */ ) external payable returns (uint256) { + return _mint(msg.sender, msg.value); + } + + receive() external payable { + _mint(msg.sender, msg.value); + } + + function _mint(address account, uint256 ethAmount) internal returns (uint256 sharesAmount) { + sharesAmount = getSharesByPooledEth(ethAmount); + + _mintShares(account, sharesAmount); + _totalPooledEther += ethAmount; + + _emitTransferAfterMintingShares(account, sharesAmount); + } } diff --git a/scripts/lido-mocks/UnsafeWithdrawalQueueMock.sol b/scripts/lido-mocks/UnsafeWithdrawalQueueMock.sol index 278c5dee..8ef5ed2b 100644 --- a/scripts/lido-mocks/UnsafeWithdrawalQueueMock.sol +++ b/scripts/lido-mocks/UnsafeWithdrawalQueueMock.sol @@ -466,7 +466,7 @@ contract UnsafeWithdrawalQueueMock is IWithdrawalQueue, IERC721Metadata { _lockedEtherAmount = _lockedEtherAmount + _amountOfETH; _lastFinalizedRequestId = _lastRequestIdToBeFinalized; - StETHMock(address(ST_ETH)).burn(address(this), stETHToFinalize); + StETHMock(payable(address(ST_ETH))).burn(address(this), stETHToFinalize); } function _markClaimed(uint256 _requestId) internal { diff --git a/scripts/deploy/DeployVerification.sol b/scripts/utils/DeployVerification.sol similarity index 56% rename from scripts/deploy/DeployVerification.sol rename to scripts/utils/DeployVerification.sol index 815f2fb1..a147019b 100644 --- a/scripts/deploy/DeployVerification.sol +++ b/scripts/utils/DeployVerification.sol @@ -18,56 +18,53 @@ import {IDualGovernance} from "contracts/interfaces/IDualGovernance.sol"; import {Escrow} from "contracts/Escrow.sol"; import {DualGovernanceConfig} from "contracts/libraries/DualGovernanceConfig.sol"; import {State as EscrowState} from "contracts/libraries/EscrowState.sol"; -import {DeployConfig, LidoContracts, TiebreakerSubCommitteeDeployConfig} from "./config/Config.sol"; -import {DeployedContracts} from "./DeployedContractsSet.sol"; + +import {DualGovernance} from "contracts/DualGovernance.sol"; +import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; +import { + DGSetupDeployConfig, + DGSetupDeployArtifacts, + ContractsDeployment, + DGSetupDeployedContracts, + TimelockContractDeployConfig, + TiebreakerContractDeployConfig, + TiebreakerCommitteeDeployConfig +} from "../utils/contracts-deployment.sol"; library DeployVerification { - function verify( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses, - bool onchainVotingCheck - ) internal view { - checkImmutables(contracts, dgDeployConfig, lidoAddresses); - checkContractsConfiguration(contracts, dgDeployConfig, lidoAddresses, onchainVotingCheck); + function verify(DGSetupDeployArtifacts.Context memory deployArtifact) internal view { + checkImmutables(deployArtifact); + checkContractsConfiguration(deployArtifact); } - function checkImmutables( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses - ) internal view { - checkEmergencyProtectedTimelockImmutables(contracts, dgDeployConfig); - checkEmergencyActivationCommittee(dgDeployConfig); - checkEmergencyExecutionCommittee(dgDeployConfig); - checkTimelockedGovernance(contracts, lidoAddresses); - checkTemporaryEmergencyGovernance(contracts, dgDeployConfig); - checkResealManager(contracts); - checkDualGovernanceAndEscrowImmutables(contracts, dgDeployConfig, lidoAddresses); + function checkImmutables(DGSetupDeployArtifacts.Context memory deployArtifact) internal view { + checkEmergencyProtectedTimelockImmutables( + deployArtifact.deployedContracts, deployArtifact.deployConfig.timelock.sanityCheckParams + ); + checkEmergencyActivationCommittee(deployArtifact.deployConfig); + checkEmergencyExecutionCommittee(deployArtifact.deployConfig); + checkTimelockedGovernance(deployArtifact.deployedContracts, deployArtifact.deployConfig); + checkResealManager(deployArtifact.deployedContracts); + checkDualGovernanceAndEscrowImmutables(deployArtifact.deployedContracts, deployArtifact.deployConfig); } - function checkContractsConfiguration( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses, - bool onchainVotingCheck - ) internal view { - checkAdminExecutor(contracts.adminExecutor, contracts.timelock); - checkEmergencyProtectedTimelockConfiguration(contracts, dgDeployConfig, onchainVotingCheck); - checkDualGovernanceConfiguration(contracts, dgDeployConfig, lidoAddresses); - checkTiebreakerCoreCommittee(contracts, dgDeployConfig); - - checkTiebreakerSubCommittee( - contracts, dgDeployConfig.tiebreakerConfig.influencers, contracts.tiebreakerSubCommitteeInfluencers - ); - checkTiebreakerSubCommittee( - contracts, dgDeployConfig.tiebreakerConfig.nodeOperators, contracts.tiebreakerSubCommitteeNodeOperators - ); - checkTiebreakerSubCommittee( - contracts, dgDeployConfig.tiebreakerConfig.protocols, contracts.tiebreakerSubCommitteeProtocols + function checkContractsConfiguration(DGSetupDeployArtifacts.Context memory deployArtifact) internal view { + checkAdminExecutor(deployArtifact.deployedContracts.adminExecutor, deployArtifact.deployedContracts.timelock); + checkEmergencyProtectedTimelockConfiguration( + deployArtifact.deployedContracts, deployArtifact.deployConfig.timelock ); + checkDualGovernanceConfiguration(deployArtifact.deployedContracts, deployArtifact.deployConfig); + checkTiebreakerCoreCommittee(deployArtifact.deployedContracts, deployArtifact.deployConfig.tiebreaker); + + for (uint256 i = 0; i < deployArtifact.deployedContracts.tiebreakerSubCommittees.length; i++) { + checkTiebreakerSubCommittee( + deployArtifact.deployedContracts, + deployArtifact.deployConfig.tiebreaker.committees[i], + deployArtifact.deployedContracts.tiebreakerSubCommittees[i] + ); + } - checkResealCommittee(dgDeployConfig); + checkResealCommittee(deployArtifact.deployConfig); } function checkAdminExecutor(Executor executor, IEmergencyProtectedTimelock timelock) internal view { @@ -75,83 +72,79 @@ library DeployVerification { } function checkEmergencyProtectedTimelockImmutables( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig + DGSetupDeployedContracts.Context memory deployedContracts, + EmergencyProtectedTimelock.SanityCheckParams memory sanityCheckParams ) internal view { - IEmergencyProtectedTimelock timelockInstance = contracts.timelock; + IEmergencyProtectedTimelock timelockInstance = deployedContracts.timelock; require( - EmergencyProtectedTimelock(address(timelockInstance)).MIN_EXECUTION_DELAY() - == dgDeployConfig.MIN_EXECUTION_DELAY, // TODO: property MIN_EXECUTION_DELAY is missing in interface IEmergencyProtectedTimelock + EmergencyProtectedTimelock(address(timelockInstance)).MIN_EXECUTION_DELAY() // TODO: property MIN_EXECUTION_DELAY is missing in interface IEmergencyProtectedTimelock + == sanityCheckParams.minExecutionDelay, "Incorrect parameter MIN_EXECUTION_DELAY" ); require( - timelockInstance.MAX_AFTER_SUBMIT_DELAY() == dgDeployConfig.MAX_AFTER_SUBMIT_DELAY, + timelockInstance.MAX_AFTER_SUBMIT_DELAY() == sanityCheckParams.maxAfterSubmitDelay, "Incorrect parameter MAX_AFTER_SUBMIT_DELAY" ); require( - timelockInstance.MAX_AFTER_SCHEDULE_DELAY() == dgDeployConfig.MAX_AFTER_SCHEDULE_DELAY, + timelockInstance.MAX_AFTER_SCHEDULE_DELAY() == sanityCheckParams.maxAfterScheduleDelay, "Incorrect parameter MAX_AFTER_SCHEDULE_DELAY" ); require( - timelockInstance.MAX_EMERGENCY_MODE_DURATION() == dgDeployConfig.MAX_EMERGENCY_MODE_DURATION, + timelockInstance.MAX_EMERGENCY_MODE_DURATION() == sanityCheckParams.maxEmergencyModeDuration, "Incorrect parameter MAX_EMERGENCY_MODE_DURATION" ); require( - timelockInstance.MAX_EMERGENCY_PROTECTION_DURATION() == dgDeployConfig.MAX_EMERGENCY_PROTECTION_DURATION, + timelockInstance.MAX_EMERGENCY_PROTECTION_DURATION() == sanityCheckParams.maxEmergencyProtectionDuration, "Incorrect parameter MAX_EMERGENCY_PROTECTION_DURATION" ); } function checkEmergencyProtectedTimelockConfiguration( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - bool onchainVotingCheck + DGSetupDeployedContracts.Context memory contracts, + TimelockContractDeployConfig.Context memory timelockConfig ) internal view { IEmergencyProtectedTimelock timelockInstance = contracts.timelock; + require( timelockInstance.getAdminExecutor() == address(contracts.adminExecutor), "Incorrect adminExecutor address in EmergencyProtectedTimelock" ); require( - timelockInstance.getEmergencyActivationCommittee() == dgDeployConfig.EMERGENCY_ACTIVATION_COMMITTEE, + timelockInstance.getEmergencyActivationCommittee() == timelockConfig.emergencyActivationCommittee, "Incorrect emergencyActivationCommittee address in EmergencyProtectedTimelock" ); require( - timelockInstance.getEmergencyExecutionCommittee() == dgDeployConfig.EMERGENCY_EXECUTION_COMMITTEE, + timelockInstance.getEmergencyExecutionCommittee() == timelockConfig.emergencyExecutionCommittee, "Incorrect emergencyExecutionCommittee address in EmergencyProtectedTimelock" ); IEmergencyProtectedTimelock.EmergencyProtectionDetails memory details = timelockInstance.getEmergencyProtectionDetails(); require( - details.emergencyProtectionEndsAfter == dgDeployConfig.EMERGENCY_PROTECTION_END_DATE, + details.emergencyProtectionEndsAfter == timelockConfig.emergencyProtectionEndDate, "Incorrect value for emergencyProtectionEndsAfter" ); require( - details.emergencyModeDuration == dgDeployConfig.EMERGENCY_MODE_DURATION, + details.emergencyModeDuration == timelockConfig.emergencyModeDuration, "Incorrect value for emergencyModeDuration" ); - if (!onchainVotingCheck) { - require( - details.emergencyModeEndsAfter == Timestamps.ZERO, - "Incorrect value for emergencyModeEndsAfter (Emergency mode is activated)" - ); - } + require( + details.emergencyModeEndsAfter == Timestamps.ZERO, + "Incorrect value for emergencyModeEndsAfter (Emergency mode is activated)" + ); - if (onchainVotingCheck) { - require( - timelockInstance.getEmergencyGovernance() == address(contracts.emergencyGovernance), - "Incorrect emergencyGovernance address in EmergencyProtectedTimelock" - ); - } + require( + timelockInstance.getEmergencyGovernance() == address(contracts.emergencyGovernance), + "Incorrect emergencyGovernance address in EmergencyProtectedTimelock" + ); require( - timelockInstance.getAfterSubmitDelay() == dgDeployConfig.AFTER_SUBMIT_DELAY, + timelockInstance.getAfterSubmitDelay() == timelockConfig.afterSubmitDelay, "Incorrect parameter AFTER_SUBMIT_DELAY" ); require( - timelockInstance.getAfterScheduleDelay() == dgDeployConfig.AFTER_SCHEDULE_DELAY, + timelockInstance.getAfterScheduleDelay() == timelockConfig.afterScheduleDelay, "Incorrect parameter AFTER_SCHEDULE_DELAY" ); require( @@ -167,28 +160,28 @@ library DeployVerification { timelockInstance.isEmergencyModeActive() == false, "EmergencyMode is Active in EmergencyProtectedTimelock" ); - if (onchainVotingCheck) { - require(timelockInstance.getProposalsCount() == 1, "ProposalsCount != 1 in EmergencyProtectedTimelock"); - } else { - require(timelockInstance.getProposalsCount() == 0, "ProposalsCount > 1 in EmergencyProtectedTimelock"); - } + require(timelockInstance.getProposalsCount() == 0, "ProposalsCount > 1 in EmergencyProtectedTimelock"); } - function checkEmergencyActivationCommittee(DeployConfig memory dgDeployConfig) internal pure { - require(dgDeployConfig.EMERGENCY_ACTIVATION_COMMITTEE != address(0), "Incorrect emergencyActivationCommittee"); + function checkEmergencyActivationCommittee(DGSetupDeployConfig.Context memory dgDeployConfig) internal pure { + require( + dgDeployConfig.timelock.emergencyActivationCommittee != address(0), "Incorrect emergencyActivationCommittee" + ); } - function checkEmergencyExecutionCommittee(DeployConfig memory dgDeployConfig) internal pure { - require(dgDeployConfig.EMERGENCY_EXECUTION_COMMITTEE != address(0), "Incorrect emergencyExecutionCommittee"); + function checkEmergencyExecutionCommittee(DGSetupDeployConfig.Context memory dgDeployConfig) internal pure { + require( + dgDeployConfig.timelock.emergencyExecutionCommittee != address(0), "Incorrect emergencyExecutionCommittee" + ); } function checkTimelockedGovernance( - DeployedContracts memory contracts, - LidoContracts memory lidoAddresses + DGSetupDeployedContracts.Context memory contracts, + DGSetupDeployConfig.Context memory dgDeployConfig ) internal view { TimelockedGovernance emergencyTimelockedGovernance = contracts.emergencyGovernance; require( - emergencyTimelockedGovernance.GOVERNANCE() == lidoAddresses.voting, + emergencyTimelockedGovernance.GOVERNANCE() == dgDeployConfig.timelock.emergencyGovernanceProposer, "TimelockedGovernance governance != Lido voting" ); require( @@ -197,22 +190,7 @@ library DeployVerification { ); } - function checkTemporaryEmergencyGovernance( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig - ) internal view { - TimelockedGovernance temporaryEmergencyGovernance = contracts.temporaryEmergencyGovernance; - require( - temporaryEmergencyGovernance.GOVERNANCE() == dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER, - "temporaryEmergencyGovernance governance != TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER" - ); - require( - address(temporaryEmergencyGovernance.TIMELOCK()) == address(contracts.timelock), - "Incorrect address for timelock in temporaryEmergencyGovernance" - ); - } - - function checkResealManager(DeployedContracts memory contracts) internal view { + function checkResealManager(DGSetupDeployedContracts.Context memory contracts) internal view { require( address(contracts.resealManager.EMERGENCY_PROTECTED_TIMELOCK()) == address(contracts.timelock), "Incorrect address for EMERGENCY_PROTECTED_TIMELOCK in ResealManager" @@ -220,9 +198,8 @@ library DeployVerification { } function checkDualGovernanceConfiguration( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses + DGSetupDeployedContracts.Context memory contracts, + DGSetupDeployConfig.Context memory dgDeployConfig ) internal view { IDualGovernance dg = contracts.dualGovernance; require( @@ -230,7 +207,7 @@ library DeployVerification { "Incorrect address for resealManager in DualGovernance" ); require( - address(dg.getResealCommittee()) == address(dgDeployConfig.RESEAL_COMMITTEE), + address(dg.getResealCommittee()) == address(dgDeployConfig.dualGovernance.resealCommittee), "Incorrect address for resealCommittee in DualGovernance" ); @@ -244,7 +221,8 @@ library DeployVerification { "Incorrect rageQuitSupport value in VetoSignallingEscrow" ); require( - vetoSignallingEscrow.getMinAssetsLockDuration() == dgDeployConfig.MIN_ASSETS_LOCK_DURATION, + vetoSignallingEscrow.getMinAssetsLockDuration() + == dgDeployConfig.dualGovernanceConfigProvider.minAssetsLockDuration, "Incorrect value of minAssetsLockDuration in VetoSignallingEscrow" ); @@ -272,7 +250,10 @@ library DeployVerification { // require(dg.getPersistedState() == State.Normal, "Incorrect DualGovernance persisted state"); // require(dg.getEffectiveState() == State.Normal, "Incorrect DualGovernance effective state"); // require(dg.getProposers().length == 1, "Incorrect amount of proposers"); - require(dg.isProposer(address(lidoAddresses.voting)) == true, "Lido voting is not set as a proposer"); + require( + dg.isProposer(address(dgDeployConfig.dualGovernance.adminProposer)) == true, + "Lido voting is not set as a proposer" + ); require(dg.isExecutor(address(contracts.adminExecutor)) == true, "adminExecutor is not set as an executor"); // require(dg.canSubmitProposal() == true, "DG is in incorrect state - can't submit proposal"); require(dg.getRageQuitEscrow() == address(0), "DG is in incorrect state - RageQuit started"); @@ -304,167 +285,168 @@ library DeployVerification { ITiebreaker.TiebreakerDetails memory ts = dg.getTiebreakerDetails(); require( - ts.tiebreakerActivationTimeout == dgDeployConfig.tiebreakerConfig.activationTimeout, + ts.tiebreakerActivationTimeout == dgDeployConfig.dualGovernance.tiebreakerActivationTimeout, "Incorrect parameter TIEBREAKER_CONFIG.ACTIVATION_TIMEOUT" ); require( ts.tiebreakerCommittee == address(contracts.tiebreakerCoreCommittee), "Incorrect tiebreakerCoreCommittee" ); require( - ts.sealableWithdrawalBlockers.length == dgDeployConfig.tiebreakerConfig.sealableWithdrawalBlockers.length, + ts.sealableWithdrawalBlockers.length == dgDeployConfig.dualGovernance.sealableWithdrawalBlockers.length, "Incorrect amount of sealableWithdrawalBlockers" ); - for (uint256 i = 0; i < dgDeployConfig.tiebreakerConfig.sealableWithdrawalBlockers.length; ++i) { + for (uint256 i = 0; i < dgDeployConfig.dualGovernance.sealableWithdrawalBlockers.length; ++i) { require( - ts.sealableWithdrawalBlockers[i] == dgDeployConfig.tiebreakerConfig.sealableWithdrawalBlockers[i], + ts.sealableWithdrawalBlockers[i] == dgDeployConfig.dualGovernance.sealableWithdrawalBlockers[i], "Incorrect sealableWithdrawalBlocker" ); } } function checkDualGovernanceAndEscrowImmutables( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig, - LidoContracts memory lidoAddresses + DGSetupDeployedContracts.Context memory contracts, + DGSetupDeployConfig.Context memory dgDeployConfig ) internal view { IDualGovernance dg = contracts.dualGovernance; require( address(dg.TIMELOCK()) == address(contracts.timelock), "Incorrect address for timelock in DualGovernance" ); require( - dg.MIN_TIEBREAKER_ACTIVATION_TIMEOUT() == dgDeployConfig.tiebreakerConfig.minActivationTimeout, + dg.MIN_TIEBREAKER_ACTIVATION_TIMEOUT() + == dgDeployConfig.dualGovernance.sanityCheckParams.minTiebreakerActivationTimeout, "Incorrect parameter TIEBREAKER_CONFIG.MIN_ACTIVATION_TIMEOUT" ); require( - dg.MAX_TIEBREAKER_ACTIVATION_TIMEOUT() == dgDeployConfig.tiebreakerConfig.maxActivationTimeout, + dg.MAX_TIEBREAKER_ACTIVATION_TIMEOUT() + == dgDeployConfig.dualGovernance.sanityCheckParams.maxTiebreakerActivationTimeout, "Incorrect parameter TIEBREAKER_CONFIG.MAX_ACTIVATION_TIMEOUT" ); require( - dg.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT() == dgDeployConfig.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT, + dg.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT() + == dgDeployConfig.dualGovernance.sanityCheckParams.maxSealableWithdrawalBlockersCount, "Incorrect parameter MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT" ); Escrow escrowTemplate = Escrow(payable(address(IEscrowBase(dg.getVetoSignallingEscrow()).ESCROW_MASTER_COPY()))); require(escrowTemplate.DUAL_GOVERNANCE() == dg, "Escrow has incorrect DualGovernance address"); - require(escrowTemplate.ST_ETH() == lidoAddresses.stETH, "Escrow has incorrect StETH address"); - require(escrowTemplate.WST_ETH() == lidoAddresses.wstETH, "Escrow has incorrect WstETH address"); require( - escrowTemplate.WITHDRAWAL_QUEUE() == lidoAddresses.withdrawalQueue, + escrowTemplate.ST_ETH() == dgDeployConfig.dualGovernance.signallingTokens.stETH, + "Escrow has incorrect StETH address" + ); + require( + escrowTemplate.WST_ETH() == dgDeployConfig.dualGovernance.signallingTokens.wstETH, + "Escrow has incorrect WstETH address" + ); + require( + escrowTemplate.WITHDRAWAL_QUEUE() == dgDeployConfig.dualGovernance.signallingTokens.withdrawalQueue, "Escrow has incorrect WithdrawalQueue address" ); require( - escrowTemplate.MIN_WITHDRAWALS_BATCH_SIZE() == dgDeployConfig.MIN_WITHDRAWALS_BATCH_SIZE, + escrowTemplate.MIN_WITHDRAWALS_BATCH_SIZE() + == dgDeployConfig.dualGovernance.sanityCheckParams.minWithdrawalsBatchSize, "Incorrect parameter MIN_WITHDRAWALS_BATCH_SIZE" ); require( - escrowTemplate.MAX_MIN_ASSETS_LOCK_DURATION() == dgDeployConfig.MAX_MIN_ASSETS_LOCK_DURATION, + escrowTemplate.MAX_MIN_ASSETS_LOCK_DURATION() + == dgDeployConfig.dualGovernance.sanityCheckParams.maxMinAssetsLockDuration, "Incorrect parameter MAX_MIN_ASSETS_LOCK_DURATION" ); DualGovernanceConfig.Context memory dgConfig = dg.getConfigProvider().getDualGovernanceConfig(); + DualGovernanceConfig.Context memory dgConfigProviderConfig = dgDeployConfig.dualGovernanceConfigProvider; require( - dgConfig.firstSealRageQuitSupport == dgDeployConfig.FIRST_SEAL_RAGE_QUIT_SUPPORT, + dgConfig.firstSealRageQuitSupport == dgConfigProviderConfig.firstSealRageQuitSupport, "Incorrect parameter FIRST_SEAL_RAGE_QUIT_SUPPORT" ); + require( - dgConfig.secondSealRageQuitSupport == dgDeployConfig.SECOND_SEAL_RAGE_QUIT_SUPPORT, + dgConfig.secondSealRageQuitSupport == dgConfigProviderConfig.secondSealRageQuitSupport, "Incorrect parameter SECOND_SEAL_RAGE_QUIT_SUPPORT" ); require( - dgConfig.minAssetsLockDuration == dgDeployConfig.MIN_ASSETS_LOCK_DURATION, + dgConfig.minAssetsLockDuration == dgConfigProviderConfig.minAssetsLockDuration, "Incorrect parameter MIN_ASSETS_LOCK_DURATION" ); require( - dgConfig.vetoSignallingMinDuration == dgDeployConfig.VETO_SIGNALLING_MIN_DURATION, + dgConfig.vetoSignallingMinDuration == dgConfigProviderConfig.vetoSignallingMinDuration, "Incorrect parameter VETO_SIGNALLING_MIN_DURATION" ); require( - dgConfig.vetoSignallingMaxDuration == dgDeployConfig.VETO_SIGNALLING_MAX_DURATION, + dgConfig.vetoSignallingMaxDuration == dgConfigProviderConfig.vetoSignallingMaxDuration, "Incorrect parameter VETO_SIGNALLING_MAX_DURATION" ); require( - dgConfig.vetoSignallingMinActiveDuration == dgDeployConfig.VETO_SIGNALLING_MIN_ACTIVE_DURATION, + dgConfig.vetoSignallingMinActiveDuration == dgConfigProviderConfig.vetoSignallingMinActiveDuration, "Incorrect parameter VETO_SIGNALLING_MIN_ACTIVE_DURATION" ); require( - dgConfig.vetoSignallingDeactivationMaxDuration == dgDeployConfig.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION, + dgConfig.vetoSignallingDeactivationMaxDuration + == dgConfigProviderConfig.vetoSignallingDeactivationMaxDuration, "Incorrect parameter VETO_SIGNALLING_DEACTIVATION_MAX_DURATION" ); require( - dgConfig.vetoCooldownDuration == dgDeployConfig.VETO_COOLDOWN_DURATION, + dgConfig.vetoCooldownDuration == dgConfigProviderConfig.vetoCooldownDuration, "Incorrect parameter VETO_COOLDOWN_DURATION" ); require( - dgConfig.rageQuitExtensionPeriodDuration == dgDeployConfig.RAGE_QUIT_EXTENSION_PERIOD_DURATION, + dgConfig.rageQuitExtensionPeriodDuration == dgConfigProviderConfig.rageQuitExtensionPeriodDuration, "Incorrect parameter RAGE_QUIT_EXTENSION_PERIOD_DURATION" ); require( - dgConfig.rageQuitEthWithdrawalsMinDelay == dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY, + dgConfig.rageQuitEthWithdrawalsMinDelay == dgConfigProviderConfig.rageQuitEthWithdrawalsMinDelay, "Incorrect parameter RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY" ); require( - dgConfig.rageQuitEthWithdrawalsMaxDelay == dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY, + dgConfig.rageQuitEthWithdrawalsMaxDelay == dgConfigProviderConfig.rageQuitEthWithdrawalsMaxDelay, "Incorrect parameter RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY" ); require( - dgConfig.rageQuitEthWithdrawalsDelayGrowth == dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH, + dgConfig.rageQuitEthWithdrawalsDelayGrowth == dgConfigProviderConfig.rageQuitEthWithdrawalsDelayGrowth, "Incorrect parameter RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH" ); } function checkTiebreakerCoreCommittee( - DeployedContracts memory contracts, - DeployConfig memory dgDeployConfig + DGSetupDeployedContracts.Context memory contracts, + TiebreakerContractDeployConfig.Context memory tiebreakerConfig ) internal view { TiebreakerCoreCommittee tcc = contracts.tiebreakerCoreCommittee; require(tcc.owner() == address(contracts.adminExecutor), "TiebreakerCoreCommittee owner != adminExecutor"); require( - tcc.getTimelockDuration() == dgDeployConfig.tiebreakerConfig.executionDelay, + tcc.getTimelockDuration() == tiebreakerConfig.executionDelay, "Incorrect parameter TIEBREAKER_CONFIG.EXECUTION_DELAY" ); - require( - tcc.isMember(address(contracts.tiebreakerSubCommitteeInfluencers)) == true, - "Influencers sub committee is not a member of TiebreakerCoreCommittee" - ); - - require( - tcc.isMember(address(contracts.tiebreakerSubCommitteeNodeOperators)) == true, - "NodeOperators sub committee is not a member of TiebreakerCoreCommittee" - ); - - require( - tcc.isMember(address(contracts.tiebreakerSubCommitteeProtocols)) == true, - "Protocols sub committee is not a member of TiebreakerCoreCommittee" - ); + for (uint256 i = 0; i < contracts.tiebreakerSubCommittees.length; ++i) { + require( + tcc.isMember(address(contracts.tiebreakerSubCommittees[i])) == true, + "Incorrect member of TiebreakerCoreCommittee" + ); + } - require( - tcc.getQuorum() == dgDeployConfig.tiebreakerConfig.quorum, "Incorrect quorum in TiebreakerCoreCommittee" - ); + require(tcc.getQuorum() == tiebreakerConfig.quorum, "Incorrect quorum in TiebreakerCoreCommittee"); require(tcc.getProposalsLength() == 0, "Incorrect proposals count in TiebreakerCoreCommittee"); } function checkTiebreakerSubCommittee( - DeployedContracts memory contracts, - TiebreakerSubCommitteeDeployConfig memory dgTiebreakerSubCommitteeDeployConfig, + DGSetupDeployedContracts.Context memory contracts, + TiebreakerCommitteeDeployConfig memory committeesConfig, TiebreakerSubCommittee tsc ) internal view { require(tsc.owner() == address(contracts.adminExecutor), "TiebreakerSubCommittee owner != adminExecutor"); require(tsc.getTimelockDuration() == Durations.from(0), "TiebreakerSubCommittee timelock should be 0"); - address[] memory members = dgTiebreakerSubCommitteeDeployConfig.members; + address[] memory members = committeesConfig.members; for (uint256 i = 0; i < members.length; ++i) { require(tsc.isMember(members[i]) == true, "Incorrect member of TiebreakerSubCommittee"); } - require( - tsc.getQuorum() == dgTiebreakerSubCommitteeDeployConfig.quorum, "Incorrect quorum in TiebreakerSubCommittee" - ); + require(tsc.getQuorum() == committeesConfig.quorum, "Incorrect quorum in TiebreakerSubCommittee"); require(tsc.getProposalsLength() == 0, "Incorrect proposals count in TiebreakerSubCommittee"); } - function checkResealCommittee(DeployConfig memory dgDeployConfig) internal pure { - require(dgDeployConfig.RESEAL_COMMITTEE != address(0), "Incorrect resealCommittee"); + function checkResealCommittee(DGSetupDeployConfig.Context memory dgDeployConfig) internal pure { + require(dgDeployConfig.dualGovernance.resealCommittee != address(0), "Incorrect resealCommittee"); } } diff --git a/scripts/utils/config-files.sol b/scripts/utils/config-files.sol new file mode 100644 index 00000000..5fcc2d40 --- /dev/null +++ b/scripts/utils/config-files.sol @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {Vm} from "forge-std/Vm.sol"; +import {stdJson} from "forge-std/stdJson.sol"; +import {stdToml} from "forge-std/StdToml.sol"; + +import {Duration, Durations} from "contracts/types/Duration.sol"; +import {Timestamp, Timestamps} from "contracts/types/Timestamp.sol"; +import {PercentD16, PercentsD16} from "contracts/types/PercentD16.sol"; + +// solhint-disable-next-line const-name-snakecase +Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + +enum ConfigFormat { + JSON, + TOML +} + +error EmptyFilePath(); +error InvalidConfigFormat(uint256 format); +error UnsupportedFileFormat(string format); + +function getFileFormatByPath(string memory path) pure returns (ConfigFormat) { + // solhint-disable-next-line custom-errors + if (bytes(path).length == 0) { + revert EmptyFilePath(); + } + + string[] memory pathSplit = vm.split(path, "."); + + string memory fileFormat = pathSplit[pathSplit.length - 1]; + bytes32 fileExtensionDigest = keccak256(bytes(vm.toLowercase(fileFormat))); + + if (fileExtensionDigest == keccak256(bytes("toml"))) { + return ConfigFormat.TOML; + } else if (fileExtensionDigest == keccak256(bytes("json"))) { + return ConfigFormat.JSON; + } + revert UnsupportedFileFormat(fileFormat); +} + +library ConfigFileReader { + struct Context { + ConfigFormat format; + string content; + } + + function load(string memory path) internal view returns (Context memory ctx) { + ctx.format = getFileFormatByPath(path); + ctx.content = vm.readFile(path); + } + + function readUint(Context memory ctx, string memory key) internal pure returns (uint256) { + if (ctx.format == ConfigFormat.JSON) return stdJson.readUint(ctx.content, key); + if (ctx.format == ConfigFormat.TOML) return stdToml.readUint(ctx.content, key); + revert InvalidConfigFormat(uint256(ctx.format)); + } + + function readDuration(Context memory ctx, string memory key) internal pure returns (Duration) { + return Durations.from(readUint(ctx, key)); + } + + function readTimestamp(Context memory ctx, string memory key) internal pure returns (Timestamp) { + return Timestamps.from(readUint(ctx, key)); + } + + function readPercentD16BP(Context memory ctx, string memory key) internal pure returns (PercentD16) { + return PercentsD16.fromBasisPoints(readUint(ctx, key)); + } + + function readAddress(Context memory ctx, string memory key) internal pure returns (address) { + if (ctx.format == ConfigFormat.JSON) return stdJson.readAddress(ctx.content, key); + if (ctx.format == ConfigFormat.TOML) return stdToml.readAddress(ctx.content, key); + revert InvalidConfigFormat(uint256(ctx.format)); + } + + function readAddressArray(Context memory ctx, string memory key) internal pure returns (address[] memory) { + if (ctx.format == ConfigFormat.JSON) return stdJson.readAddressArray(ctx.content, key); + if (ctx.format == ConfigFormat.TOML) return stdToml.readAddressArray(ctx.content, key); + revert InvalidConfigFormat(uint256(ctx.format)); + } +} + +library ConfigFileBuilder { + struct Context { + string id; + string content; + } + + function create() internal returns (Context memory ctx) { + ctx.id = _nextId(); + } + + function write(Context memory ctx, string memory path) internal { + ConfigFormat outputFileFormat = getFileFormatByPath(path); + + if (outputFileFormat == ConfigFormat.JSON) { + stdJson.write(ctx.content, path); + } else if (outputFileFormat == ConfigFormat.TOML) { + stdToml.write(ctx.content, path); + } else { + revert InvalidConfigFormat(uint256(outputFileFormat)); + } + } + + function set(Context memory ctx, string memory key, uint256 value) internal returns (Context memory) { + ctx.content = stdJson.serialize(ctx.id, key, value); + return ctx; + } + + function set(Context memory ctx, string memory key, Duration value) internal returns (Context memory) { + return set(ctx, key, value.toSeconds()); + } + + function set(Context memory ctx, string memory key, Timestamp value) internal returns (Context memory) { + return set(ctx, key, value.toSeconds()); + } + + function set(Context memory ctx, string memory key, PercentD16 value) internal returns (Context memory) { + return set(ctx, key, value.toUint256()); + } + + function set(Context memory ctx, string memory key, address value) internal returns (Context memory) { + ctx.content = stdJson.serialize(ctx.id, key, value); + return ctx; + } + + function set(Context memory ctx, string memory key, address[] memory value) internal returns (Context memory) { + ctx.content = stdJson.serialize(ctx.id, key, value); + return ctx; + } + + function set(Context memory ctx, string memory key, string[] memory value) internal returns (Context memory) { + ctx.content = stdJson.serialize(ctx.id, key, value); + return ctx; + } + + function set(Context memory ctx, string memory key, string memory value) internal returns (Context memory) { + ctx.content = stdJson.serialize(ctx.id, key, value); + return ctx; + } + + function _nextId() private returns (string memory id) { + bytes32 slot = keccak256("config-files.storage.counter"); + + uint256 count = uint256(vm.load(address(this), slot)) + 1; + vm.store(address(this), slot, bytes32(count)); + return string(abi.encodePacked(address(this), count)); + } +} + +library JsonKeys { + function root(string memory prefix) internal pure returns (string memory) { + if (bytes(prefix).length == 0) { + return "$"; + } + if (bytes(prefix)[0] == bytes1("$") || bytes(prefix)[0] == bytes1(".")) { + return prefix; + } + return string.concat("$", ".", prefix); + } + + function key(string memory prefix, string memory key) internal pure returns (string memory) { + return string.concat(prefix, ".", key); + } + + function index(string memory prefix, string memory key, uint256 index) internal pure returns (string memory) { + return string.concat(prefix, ".", key, "[", vm.toString(index), "]"); + } +} diff --git a/scripts/utils/contracts-deployment.sol b/scripts/utils/contracts-deployment.sol new file mode 100644 index 00000000..7b163bbf --- /dev/null +++ b/scripts/utils/contracts-deployment.sol @@ -0,0 +1,926 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +/* solhint-disable no-console */ + +import {Vm} from "forge-std/Vm.sol"; +import {console} from "forge-std/console.sol"; + +import {IStETH} from "contracts/interfaces/IStETH.sol"; +import {IWstETH} from "contracts/interfaces/IWstETH.sol"; +import {ITimelock} from "contracts/interfaces/ITimelock.sol"; +import {IWithdrawalQueue} from "contracts/interfaces/IWithdrawalQueue.sol"; + +import {Duration, Durations} from "contracts/types/Duration.sol"; +import {Timestamp, Timestamps} from "contracts/types/Timestamp.sol"; + +import {Escrow} from "contracts/Escrow.sol"; +import {Executor} from "contracts/Executor.sol"; +import {ResealManager} from "contracts/ResealManager.sol"; +import {DualGovernance} from "contracts/DualGovernance.sol"; +import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; +import {DualGovernanceConfig} from "contracts/libraries/DualGovernanceConfig.sol"; +import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; +import {ImmutableDualGovernanceConfigProvider} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; + +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; +import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; + +import {DeployFiles} from "./deploy-files.sol"; +import {ConfigFileReader, ConfigFileBuilder, JsonKeys} from "./config-files.sol"; + +// solhint-disable-next-line const-name-snakecase +Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + +error InvalidParameter(string parameter); +error InvalidChainId(uint256 actual, uint256 expected); + +using JsonKeys for string; +using ConfigFileBuilder for ConfigFileBuilder.Context; + +library TimelockContractDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + + struct Context { + Duration afterSubmitDelay; + Duration afterScheduleDelay; + EmergencyProtectedTimelock.SanityCheckParams sanityCheckParams; + Duration emergencyModeDuration; + Timestamp emergencyProtectionEndDate; + address emergencyGovernanceProposer; + address emergencyActivationCommittee; + address emergencyExecutionCommittee; + } + + function load(string memory configFilePath, string memory configRootKey) internal returns (Context memory ctx) { + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + + string memory $ = configRootKey.root(); + string memory $sanityCheckParams = $.key("sanity_check_params"); + string memory $emergencyProtection = $.key("emergency_protection"); + + return Context({ + afterSubmitDelay: file.readDuration($.key("after_submit_delay")), + afterScheduleDelay: file.readDuration($.key("after_schedule_delay")), + sanityCheckParams: EmergencyProtectedTimelock.SanityCheckParams({ + minExecutionDelay: file.readDuration($sanityCheckParams.key("min_execution_delay")), + maxAfterSubmitDelay: file.readDuration($sanityCheckParams.key("max_after_submit_delay")), + maxAfterScheduleDelay: file.readDuration($sanityCheckParams.key("max_after_schedule_delay")), + maxEmergencyModeDuration: file.readDuration($sanityCheckParams.key("max_emergency_mode_duration")), + maxEmergencyProtectionDuration: file.readDuration($sanityCheckParams.key("max_emergency_protection_duration")) + }), + emergencyGovernanceProposer: file.readAddress($emergencyProtection.key("emergency_governance_proposer")), + emergencyActivationCommittee: file.readAddress($emergencyProtection.key("emergency_activation_committee")), + emergencyExecutionCommittee: file.readAddress($emergencyProtection.key("emergency_execution_committee")), + emergencyModeDuration: file.readDuration($emergencyProtection.key("emergency_mode_duration")), + emergencyProtectionEndDate: file.readTimestamp($emergencyProtection.key("emergency_protection_end_date")) + }); + } + + function validate(Context memory ctx) internal { + if (ctx.afterSubmitDelay > ctx.sanityCheckParams.maxAfterSubmitDelay) { + revert InvalidParameter("after_submit_delay"); + } + + if (ctx.afterScheduleDelay > ctx.sanityCheckParams.maxAfterScheduleDelay) { + revert InvalidParameter("after_schedule_delay"); + } + + if (ctx.emergencyModeDuration > ctx.sanityCheckParams.maxEmergencyModeDuration) { + revert InvalidParameter("emergency_mode_duration"); + } + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("after_schedule_delay", ctx.afterScheduleDelay); + builder.set("after_submit_delay", ctx.afterSubmitDelay); + builder.set("sanity_check_params", _sanityCheckParamsToJSON(ctx)); + builder.set("emergency_protection", _emergencyProtectionToJSON(ctx)); + + return builder.content; + } + + function _sanityCheckParamsToJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("min_execution_delay", ctx.sanityCheckParams.minExecutionDelay); + builder.set("max_after_submit_delay", ctx.sanityCheckParams.maxAfterSubmitDelay); + builder.set("max_after_schedule_delay", ctx.sanityCheckParams.maxAfterScheduleDelay); + builder.set("max_emergency_mode_duration", ctx.sanityCheckParams.maxEmergencyModeDuration); + builder.set("max_emergency_protection_duration", ctx.sanityCheckParams.maxEmergencyProtectionDuration); + + return builder.content; + } + + function _emergencyProtectionToJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("emergency_mode_duration", ctx.emergencyModeDuration); + builder.set("emergency_protection_end_date", ctx.emergencyProtectionEndDate); + builder.set("emergency_governance_proposer", ctx.emergencyGovernanceProposer); + builder.set("emergency_activation_committee", ctx.emergencyActivationCommittee); + builder.set("emergency_execution_committee", ctx.emergencyExecutionCommittee); + + return builder.content; + } +} + +struct TiebreakerCommitteeDeployConfig { + uint256 quorum; + address[] members; +} + +library TiebreakerContractDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + + struct Context { + uint256 quorum; + uint256 committeesCount; + Duration executionDelay; + TiebreakerCommitteeDeployConfig[] committees; + } + + function load(string memory configFilePath, string memory configRootKey) internal returns (Context memory) { + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + + string memory $ = JsonKeys.root(configRootKey); + + uint256 tiebreakerCommitteesCount = file.readUint($.key("committees_count")); + + TiebreakerCommitteeDeployConfig[] memory tiebreakerCommitteeConfigs = + new TiebreakerCommitteeDeployConfig[](tiebreakerCommitteesCount); + + for (uint256 i = 0; i < tiebreakerCommitteeConfigs.length; ++i) { + string memory $committees = $.index("committees", i); + tiebreakerCommitteeConfigs[i].quorum = file.readUint($committees.key("quorum")); + tiebreakerCommitteeConfigs[i].members = file.readAddressArray($committees.key("members")); + } + + return Context({ + quorum: file.readUint($.key("quorum")), + executionDelay: file.readDuration($.key("execution_delay")), + committeesCount: tiebreakerCommitteesCount, + committees: tiebreakerCommitteeConfigs + }); + } + + function validate(Context memory ctx) internal { + if (ctx.quorum == 0 || ctx.quorum > ctx.committeesCount) { + revert InvalidParameter("tiebreaker.quorum"); + } + + if (ctx.committeesCount != ctx.committees.length) { + revert InvalidParameter("tiebreaker.committees_count"); + } + + for (uint256 i = 0; i < ctx.committeesCount; ++i) { + if (ctx.committees[i].quorum == 0 || ctx.committees[i].quorum > ctx.committees[i].members.length) { + revert InvalidParameter(string.concat("tiebreaker.committees[", vm.toString(i), "].quorum")); + } + } + } + + function toJSON(Context memory ctx) internal returns (string memory) { + string[] memory tiebreakerCommitteesContent = new string[](ctx.committees.length); + + for (uint256 i = 0; i < tiebreakerCommitteesContent.length; ++i) { + // forgefmt: disable-next-item + tiebreakerCommitteesContent[i] = ConfigFileBuilder.create() + .set("quorum", ctx.committees[i].quorum) + .set("members", ctx.committees[i].members) + .content; + } + + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("quorum", ctx.quorum); + builder.set("committees_count", ctx.committeesCount); + builder.set("execution_delay", ctx.executionDelay); + builder.set("committees", tiebreakerCommitteesContent); + + return builder.content; + } +} + +library DualGovernanceContractDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + + struct Context { + address adminProposer; + address resealCommittee; + address proposalsCanceller; + address[] sealableWithdrawalBlockers; + Duration tiebreakerActivationTimeout; + DualGovernance.SignallingTokens signallingTokens; + DualGovernance.SanityCheckParams sanityCheckParams; + } + + function load(string memory configFilePath, string memory configRootKey) internal returns (Context memory) { + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + + string memory $ = configRootKey.root(); + string memory $sanity_check = $.key("sanity_check_params"); + string memory $signalling_tokens = $.key("signalling_tokens"); + + return Context({ + adminProposer: file.readAddress($.key("admin_proposer")), + resealCommittee: file.readAddress($.key("reseal_committee")), + proposalsCanceller: file.readAddress($.key("proposals_canceller")), + tiebreakerActivationTimeout: file.readDuration($.key("tiebreaker_activation_timeout")), + sealableWithdrawalBlockers: file.readAddressArray($.key("sealable_withdrawal_blockers")), + sanityCheckParams: DualGovernance.SanityCheckParams({ + minWithdrawalsBatchSize: file.readUint($sanity_check.key("min_withdrawals_batch_size")), + minTiebreakerActivationTimeout: file.readDuration($sanity_check.key("min_tiebreaker_activation_timeout")), + maxTiebreakerActivationTimeout: file.readDuration($sanity_check.key("max_tiebreaker_activation_timeout")), + maxSealableWithdrawalBlockersCount: file.readUint($sanity_check.key("max_sealable_withdrawal_blockers_count")), + maxMinAssetsLockDuration: file.readDuration($sanity_check.key("max_min_assets_lock_duration")) + }), + signallingTokens: DualGovernance.SignallingTokens({ + stETH: IStETH(file.readAddress($signalling_tokens.key("st_eth"))), + wstETH: IWstETH(file.readAddress($signalling_tokens.key("wst_eth"))), + withdrawalQueue: IWithdrawalQueue(file.readAddress($signalling_tokens.key("withdrawal_queue"))) + }) + }); + } + + function validate(Context memory ctx) internal { + if (ctx.sanityCheckParams.minTiebreakerActivationTimeout > ctx.sanityCheckParams.maxTiebreakerActivationTimeout) + { + revert InvalidParameter("dual_governance.sanity_check_params.min_activation_timeout"); + } + + if ( + ctx.tiebreakerActivationTimeout > ctx.sanityCheckParams.maxTiebreakerActivationTimeout + || ctx.tiebreakerActivationTimeout < ctx.sanityCheckParams.minTiebreakerActivationTimeout + ) { + revert InvalidParameter("dual_governance.tiebreaker.activation_timeout"); + } + + if (ctx.sanityCheckParams.maxSealableWithdrawalBlockersCount == 0) { + revert InvalidParameter("max_sealable_withdrawal_blockers_count"); + } + + if (ctx.sealableWithdrawalBlockers.length > ctx.sanityCheckParams.maxSealableWithdrawalBlockersCount) { + revert InvalidParameter("tiebreaker.sealable_withdrawal_blockers"); + } + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + // forgefmt: disable-next-item + { + ConfigFileBuilder.Context memory sanityCheckParamsBuilder = ConfigFileBuilder.create(); + + sanityCheckParamsBuilder.set("min_withdrawals_batch_size", ctx.sanityCheckParams.minWithdrawalsBatchSize); + sanityCheckParamsBuilder.set("min_tiebreaker_activation_timeout", ctx.sanityCheckParams.minTiebreakerActivationTimeout); + sanityCheckParamsBuilder.set("max_tiebreaker_activation_timeout", ctx.sanityCheckParams.maxTiebreakerActivationTimeout); + sanityCheckParamsBuilder.set("max_sealable_withdrawal_blockers_count", ctx.sanityCheckParams.maxSealableWithdrawalBlockersCount); + sanityCheckParamsBuilder.set("max_min_assets_lock_duration", ctx.sanityCheckParams.maxMinAssetsLockDuration); + + ConfigFileBuilder.Context memory signallingTokensBuilder = ConfigFileBuilder.create(); + + signallingTokensBuilder.set("st_eth", address(ctx.signallingTokens.stETH)); + signallingTokensBuilder.set("wst_eth", address(ctx.signallingTokens.wstETH)); + signallingTokensBuilder.set("withdrawal_queue", address(ctx.signallingTokens.withdrawalQueue)); + + builder.set("admin_proposer", ctx.adminProposer); + builder.set("reseal_committee", ctx.resealCommittee); + builder.set("proposals_canceller", ctx.proposalsCanceller); + builder.set("signalling_tokens", signallingTokensBuilder.content); + builder.set("sanity_check_params", sanityCheckParamsBuilder.content); + builder.set("tiebreaker_activation_timeout", ctx.tiebreakerActivationTimeout); + builder.set("sealable_withdrawal_blockers", ctx.sealableWithdrawalBlockers); + } + + return builder.content; + } +} + +library DualGovernanceConfigProviderContractDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + + function load( + string memory configFilePath, + string memory configRootKey + ) internal returns (DualGovernanceConfig.Context memory ctx) { + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + string memory $ = configRootKey.root(); + + return DualGovernanceConfig.Context({ + firstSealRageQuitSupport: file.readPercentD16BP($.key("first_seal_rage_quit_support")), + secondSealRageQuitSupport: file.readPercentD16BP($.key("second_seal_rage_quit_support")), + // + minAssetsLockDuration: file.readDuration($.key("min_assets_lock_duration")), + // + vetoSignallingMinDuration: file.readDuration($.key("veto_signalling_min_duration")), + vetoSignallingMaxDuration: file.readDuration($.key("veto_signalling_max_duration")), + vetoSignallingMinActiveDuration: file.readDuration($.key("veto_signalling_min_active_duration")), + vetoSignallingDeactivationMaxDuration: file.readDuration($.key("veto_signalling_max_duration")), + vetoCooldownDuration: file.readDuration($.key("veto_cooldown_duration")), + // + rageQuitExtensionPeriodDuration: file.readDuration($.key("rage_quit_extension_period_duration")), + rageQuitEthWithdrawalsMinDelay: file.readDuration($.key("rage_quit_eth_withdrawals_min_delay")), + rageQuitEthWithdrawalsMaxDelay: file.readDuration($.key("rage_quit_eth_withdrawals_max_delay")), + rageQuitEthWithdrawalsDelayGrowth: file.readDuration($.key("rage_quit_eth_withdrawals_delay_growth")) + }); + } + + function validate(DualGovernanceConfig.Context memory ctx) internal returns (string memory) { + DualGovernanceConfig.validate(ctx); + } + + function toJSON(DualGovernanceConfig.Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + // forgefmt: disable-next-item + { + builder.set("first_seal_rage_quit_support", ctx.firstSealRageQuitSupport.toUint256() / 1e14); + builder.set("second_seal_rage_quit_support", ctx.secondSealRageQuitSupport.toUint256() / 1e14); + + builder.set("min_assets_lock_duration", ctx.minAssetsLockDuration); + + builder.set("veto_signalling_min_duration", ctx.vetoSignallingMinDuration); + builder.set("veto_signalling_min_active_duration", ctx.vetoSignallingMinActiveDuration); + builder.set("veto_signalling_max_duration", ctx.vetoSignallingMaxDuration); + builder.set("veto_signalling_deactivation_max_duration", ctx.vetoSignallingDeactivationMaxDuration); + builder.set("veto_cooldown_duration", ctx.vetoCooldownDuration); + + builder.set("rage_quit_eth_withdrawals_delay_growth", ctx.rageQuitEthWithdrawalsDelayGrowth); + builder.set("rage_quit_eth_withdrawals_max_delay", ctx.rageQuitEthWithdrawalsMaxDelay); + builder.set("rage_quit_eth_withdrawals_min_delay",ctx.rageQuitEthWithdrawalsMinDelay); + builder.set("rage_quit_extension_period_duration", ctx.rageQuitExtensionPeriodDuration); + } + + return builder.content; + } +} + +library DGSetupDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + using TimelockContractDeployConfig for TimelockContractDeployConfig.Context; + using TiebreakerContractDeployConfig for TiebreakerContractDeployConfig.Context; + using DualGovernanceContractDeployConfig for DualGovernanceContractDeployConfig.Context; + using DualGovernanceConfigProviderContractDeployConfig for DualGovernanceConfig.Context; + + struct Context { + uint256 chainId; + TimelockContractDeployConfig.Context timelock; + TiebreakerContractDeployConfig.Context tiebreaker; + DualGovernanceContractDeployConfig.Context dualGovernance; + DualGovernanceConfig.Context dualGovernanceConfigProvider; + } + + function load(string memory configFilePath) internal returns (Context memory ctx) { + return load(configFilePath, ""); + } + + function load(string memory configFilePath, string memory configRootKey) internal returns (Context memory ctx) { + string memory $ = configRootKey.root(); + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + + ctx.chainId = file.readUint($.key("chain_id")); + ctx.timelock = TimelockContractDeployConfig.load(configFilePath, $.key("timelock")); + ctx.tiebreaker = TiebreakerContractDeployConfig.load(configFilePath, $.key("tiebreaker")); + ctx.dualGovernance = DualGovernanceContractDeployConfig.load(configFilePath, $.key("dual_governance")); + ctx.dualGovernanceConfigProvider = DualGovernanceConfigProviderContractDeployConfig.load( + configFilePath, $.key("dual_governance_config_provider") + ); + } + + function validate(Context memory ctx) internal { + ctx.timelock.validate(); + ctx.tiebreaker.validate(); + ctx.dualGovernance.validate(); + ctx.dualGovernanceConfigProvider.validate(); + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("chain_id", ctx.chainId); + builder.set("timelock", ctx.timelock.toJSON()); + builder.set("tiebreaker", ctx.tiebreaker.toJSON()); + builder.set("dual_governance", ctx.dualGovernance.toJSON()); + builder.set("dual_governance_config_provider", ctx.dualGovernanceConfigProvider.toJSON()); + + return builder.content; + } +} + +library DGSetupDeployedContracts { + using JsonKeys for string; + using ConfigFileReader for ConfigFileReader.Context; + using ConfigFileBuilder for ConfigFileBuilder.Context; + + struct Context { + Executor adminExecutor; + Escrow escrowMasterCopy; + EmergencyProtectedTimelock timelock; + TimelockedGovernance emergencyGovernance; + ResealManager resealManager; + DualGovernance dualGovernance; + ImmutableDualGovernanceConfigProvider dualGovernanceConfigProvider; + TiebreakerCoreCommittee tiebreakerCoreCommittee; + TiebreakerSubCommittee[] tiebreakerSubCommittees; + } + + function load( + string memory deployedContractsFilePath, + string memory prefix + ) internal returns (Context memory ctx) { + string memory $ = prefix.root(); + ConfigFileReader.Context memory deployedContract = ConfigFileReader.load(deployedContractsFilePath); + + ctx.adminExecutor = Executor(payable(deployedContract.readAddress($.key("admin_executor")))); + ctx.timelock = EmergencyProtectedTimelock(deployedContract.readAddress($.key("timelock"))); + ctx.emergencyGovernance = TimelockedGovernance(deployedContract.readAddress($.key("emergency_governance"))); + ctx.resealManager = ResealManager(deployedContract.readAddress($.key("reseal_manager"))); + ctx.dualGovernance = DualGovernance(deployedContract.readAddress($.key("dual_governance"))); + ctx.escrowMasterCopy = Escrow(payable(deployedContract.readAddress($.key("escrow_master_copy")))); + ctx.dualGovernanceConfigProvider = ImmutableDualGovernanceConfigProvider( + deployedContract.readAddress($.key("dual_governance_config_provider")) + ); + ctx.tiebreakerCoreCommittee = + TiebreakerCoreCommittee(deployedContract.readAddress($.key("tiebreaker_core_committee"))); + + address[] memory tiebreakerSubCommittees = deployedContract.readAddressArray($.key("tiebreaker_sub_committees")); + ctx.tiebreakerSubCommittees = new TiebreakerSubCommittee[](tiebreakerSubCommittees.length); + for (uint256 i = 0; i < tiebreakerSubCommittees.length; ++i) { + ctx.tiebreakerSubCommittees[i] = TiebreakerSubCommittee(tiebreakerSubCommittees[i]); + } + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory configBuilder = ConfigFileBuilder.create(); + + configBuilder.set("admin_executor", address(ctx.adminExecutor)); + configBuilder.set("timelock", address(ctx.timelock)); + configBuilder.set("emergency_governance", address(ctx.emergencyGovernance)); + configBuilder.set("reseal_manager", address(ctx.resealManager)); + configBuilder.set("dual_governance", address(ctx.dualGovernance)); + configBuilder.set("escrow_master_copy", address(ctx.escrowMasterCopy)); + configBuilder.set("dual_governance_config_provider", address(ctx.dualGovernanceConfigProvider)); + configBuilder.set("tiebreaker_core_committee", address(ctx.tiebreakerCoreCommittee)); + configBuilder.set("tiebreaker_sub_committees", _getTiebreakerSubCommitteeAddresses(ctx)); + + return configBuilder.content; + } + + function print(Context memory ctx) internal pure { + console.log("DualGovernance address", address(ctx.dualGovernance)); + console.log("EscrowMasterCopy address", address(ctx.escrowMasterCopy)); + console.log("ResealManager address", address(ctx.resealManager)); + console.log("TiebreakerCoreCommittee address", address(ctx.tiebreakerCoreCommittee)); + + address[] memory tiebreakerSubCommittees = _getTiebreakerSubCommitteeAddresses(ctx); + + for (uint256 i = 0; i < tiebreakerSubCommittees.length; ++i) { + console.log("TiebreakerSubCommittee[%d] address %x", i, tiebreakerSubCommittees[i]); + } + + console.log("AdminExecutor address", address(ctx.adminExecutor)); + console.log("EmergencyProtectedTimelock address", address(ctx.timelock)); + console.log("EmergencyGovernance address", address(ctx.emergencyGovernance)); + } + + function _getTiebreakerSubCommitteeAddresses(Context memory ctx) + private + pure + returns (address[] memory tiebreakerSubCommittees) + { + tiebreakerSubCommittees = new address[](ctx.tiebreakerSubCommittees.length); + for (uint256 i = 0; i < tiebreakerSubCommittees.length; ++i) { + tiebreakerSubCommittees[i] = address(ctx.tiebreakerSubCommittees[i]); + } + } +} + +library DGSetupDeployArtifacts { + using ConfigFileBuilder for ConfigFileBuilder.Context; + using DGSetupDeployConfig for DGSetupDeployConfig.Context; + using DGSetupDeployedContracts for DGSetupDeployedContracts.Context; + + struct Context { + DGSetupDeployConfig.Context deployConfig; + DGSetupDeployedContracts.Context deployedContracts; + } + + function create( + DGSetupDeployConfig.Context memory deployConfig, + DGSetupDeployedContracts.Context memory deployedContracts + ) internal returns (Context memory ctx) { + ctx.deployConfig = deployConfig; + ctx.deployedContracts = deployedContracts; + } + + function load(string memory deployArtifactFileName) internal returns (Context memory ctx) { + string memory deployArtifactFilePath = DeployFiles.resolveDeployArtifact(deployArtifactFileName); + ctx.deployConfig = DGSetupDeployConfig.load(deployArtifactFilePath, "deploy_config"); + ctx.deployedContracts = DGSetupDeployedContracts.load(deployArtifactFilePath, "deployed_contracts"); + } + + function validate(Context memory ctx) internal { + ctx.deployConfig.validate(); + } + + function save(Context memory ctx, string memory fileName) internal { + ConfigFileBuilder.Context memory configBuilder = ConfigFileBuilder.create(); + + // forgefmt: disable-next-item + configBuilder + .set("deploy_config", ctx.deployConfig.toJSON()) + .set("deployed_contracts", ctx.deployedContracts.toJSON()) + .write(DeployFiles.resolveDeployArtifact(fileName)); + } +} + +library TGSetupDeployConfig { + struct Context { + uint256 chainId; + address governance; + TimelockContractDeployConfig.Context timelock; + } +} + +library TGSetupDeployedContracts { + struct Context { + Executor adminExecutor; + EmergencyProtectedTimelock timelock; + TimelockedGovernance timelockedGovernance; + } +} + +library TimelockedGovernanceDeployConfig { + using ConfigFileReader for ConfigFileReader.Context; + + struct Context { + uint256 chainId; + address governance; + EmergencyProtectedTimelock timelock; + } + + function load(string memory configFilePath, string memory configRootKey) internal returns (Context memory ctx) { + string memory $ = configRootKey.root(); + ConfigFileReader.Context memory file = ConfigFileReader.load(configFilePath); + + ctx.governance = file.readAddress($.key("governance")); + ctx.timelock = EmergencyProtectedTimelock(file.readAddress($.key("timelock"))); + } + + function validate(Context memory ctx) internal { + if (ctx.chainId != block.chainid) { + revert InvalidChainId({actual: block.chainid, expected: ctx.chainId}); + } + if (address(ctx.timelock) == address(0)) { + revert InvalidParameter("timelock"); + } + if (ctx.governance == address(0)) { + revert InvalidParameter("governance"); + } + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("governance", ctx.governance); + builder.set("timelock", address(ctx.timelock)); + + return builder.content; + } + + function print(Context memory ctx) internal { + console.log("Governance address", ctx.governance); + console.log("Timelock address", address(ctx.timelock)); + } +} + +library TimelockedGovernanceDeployedContracts { + using ConfigFileReader for ConfigFileReader.Context; + + struct Context { + TimelockedGovernance timelockedGovernance; + } + + function load( + string memory deployedContractsFilePath, + string memory prefix + ) internal returns (Context memory ctx) { + string memory $ = prefix.root(); + ConfigFileReader.Context memory deployedContract = ConfigFileReader.load(deployedContractsFilePath); + + ctx.timelockedGovernance = TimelockedGovernance(deployedContract.readAddress($.key("timelocked_governance"))); + } + + function toJSON(Context memory ctx) internal returns (string memory) { + ConfigFileBuilder.Context memory builder = ConfigFileBuilder.create(); + + builder.set("timelocked_governance", address(ctx.timelockedGovernance)); + + return builder.content; + } + + function print(Context memory ctx) internal { + console.log("TimelockedGovernance address", address(ctx.timelockedGovernance)); + } +} + +library ContractsDeployment { + function deployTGSetup( + address deployer, + TGSetupDeployConfig.Context memory config + ) internal returns (TGSetupDeployedContracts.Context memory contracts) { + contracts.adminExecutor = deployExecutor({owner: deployer}); + + contracts.timelock = deployEmergencyProtectedTimelock( + contracts.adminExecutor, + config.timelock.afterSubmitDelay, + config.timelock.afterScheduleDelay, + config.timelock.sanityCheckParams + ); + + contracts.timelockedGovernance = + deployTimelockedGovernance({governance: config.governance, timelock: contracts.timelock}); + + configureEmergencyProtectedTimelock(contracts.adminExecutor, contracts.timelock, config.timelock); + finalizeEmergencyProtectedTimelockDeploy( + contracts.adminExecutor, contracts.timelock, address(contracts.timelockedGovernance) + ); + } + + function deployDGSetup( + address deployer, + DGSetupDeployConfig.Context memory deployConfig + ) internal returns (DGSetupDeployedContracts.Context memory contracts) { + contracts.adminExecutor = deployExecutor({owner: deployer}); + + contracts.timelock = deployEmergencyProtectedTimelock( + contracts.adminExecutor, + deployConfig.timelock.afterSubmitDelay, + deployConfig.timelock.afterScheduleDelay, + deployConfig.timelock.sanityCheckParams + ); + + contracts.resealManager = deployResealManager(contracts.timelock); + + contracts.dualGovernanceConfigProvider = + deployDualGovernanceConfigProvider(deployConfig.dualGovernanceConfigProvider); + + contracts.dualGovernance = deployDualGovernance( + DualGovernance.DualGovernanceComponents({ + timelock: contracts.timelock, + resealManager: contracts.resealManager, + configProvider: contracts.dualGovernanceConfigProvider + }), + deployConfig.dualGovernance.signallingTokens, + deployConfig.dualGovernance.sanityCheckParams + ); + + contracts.tiebreakerCoreCommittee = deployEmptyTiebreakerCoreCommittee({ + owner: deployer, // temporary set owner to deployer, to add sub committees manually + dualGovernance: address(contracts.dualGovernance), + executionDelay: deployConfig.tiebreaker.executionDelay + }); + + contracts.tiebreakerSubCommittees = deployTiebreakerSubCommittees( + address(contracts.adminExecutor), contracts.tiebreakerCoreCommittee, deployConfig.tiebreaker.committees + ); + + configureTiebreakerCommittee( + contracts.adminExecutor, + contracts.dualGovernance, + contracts.tiebreakerCoreCommittee, + contracts.tiebreakerSubCommittees, + deployConfig.tiebreaker, + deployConfig.dualGovernance + ); + + // --- + // Finalize Setup + // --- + + configureDualGovernance( + contracts.adminExecutor, + contracts.dualGovernance, + contracts.tiebreakerCoreCommittee, + deployConfig.dualGovernance + ); + + contracts.emergencyGovernance = + configureEmergencyProtectedTimelock(contracts.adminExecutor, contracts.timelock, deployConfig.timelock); + + finalizeEmergencyProtectedTimelockDeploy( + contracts.adminExecutor, contracts.timelock, address(contracts.dualGovernance) + ); + } + + function deployExecutor(address owner) internal returns (Executor) { + return new Executor(owner); + } + + function deployEmergencyProtectedTimelock( + Executor adminExecutor, + Duration afterSubmitDelay, + Duration afterScheduleDelay, + EmergencyProtectedTimelock.SanityCheckParams memory sanityCheckParams + ) internal returns (EmergencyProtectedTimelock) { + return new EmergencyProtectedTimelock( + sanityCheckParams, address(adminExecutor), afterSubmitDelay, afterScheduleDelay + ); + } + + function deployTimelockedGovernance( + address governance, + ITimelock timelock + ) internal returns (TimelockedGovernance) { + return new TimelockedGovernance(governance, timelock); + } + + function deployResealManager(ITimelock timelock) internal returns (ResealManager) { + return new ResealManager(timelock); + } + + function deployDualGovernanceConfigProvider(DualGovernanceConfig.Context memory dgConfig) + internal + returns (ImmutableDualGovernanceConfigProvider) + { + return new ImmutableDualGovernanceConfigProvider(dgConfig); + } + + function deployDualGovernance( + DualGovernance.DualGovernanceComponents memory components, + DualGovernance.SignallingTokens memory signallingTokens, + DualGovernance.SanityCheckParams memory sanityCheckParams + ) internal returns (DualGovernance) { + return new DualGovernance(components, signallingTokens, sanityCheckParams); + } + + function deployEmptyTiebreakerCoreCommittee( + address owner, + address dualGovernance, + Duration executionDelay + ) internal returns (TiebreakerCoreCommittee) { + return new TiebreakerCoreCommittee({owner: owner, dualGovernance: dualGovernance, timelock: executionDelay}); + } + + function deployTiebreakerSubCommittees( + address owner, + TiebreakerCoreCommittee tiebreakerCoreCommittee, + TiebreakerCommitteeDeployConfig[] memory tiebreakerSubCommittees + ) internal returns (TiebreakerSubCommittee[] memory coreCommitteeMembers) { + coreCommitteeMembers = new TiebreakerSubCommittee[](tiebreakerSubCommittees.length); + + for (uint256 i = 0; i < tiebreakerSubCommittees.length; ++i) { + coreCommitteeMembers[i] = deployTiebreakerSubCommittee({ + owner: owner, + quorum: tiebreakerSubCommittees[i].quorum, + members: tiebreakerSubCommittees[i].members, + tiebreakerCoreCommittee: address(tiebreakerCoreCommittee) + }); + } + } + + function deployTiebreakerSubCommittee( + address owner, + uint256 quorum, + address[] memory members, + address tiebreakerCoreCommittee + ) internal returns (TiebreakerSubCommittee) { + return new TiebreakerSubCommittee({ + owner: owner, + executionQuorum: quorum, + committeeMembers: members, + tiebreakerCoreCommittee: tiebreakerCoreCommittee + }); + } + + function configureTiebreakerCommittee( + Executor adminExecutor, + DualGovernance dualGovernance, + TiebreakerCoreCommittee tiebreakerCoreCommittee, + TiebreakerSubCommittee[] memory tiebreakerSubCommittees, + TiebreakerContractDeployConfig.Context memory tiebreakerConfig, + DualGovernanceContractDeployConfig.Context memory dgDeployConfig + ) internal { + address[] memory coreCommitteeMemberAddresses = new address[](tiebreakerSubCommittees.length); + + for (uint256 i = 0; i < coreCommitteeMemberAddresses.length; ++i) { + coreCommitteeMemberAddresses[i] = address(tiebreakerSubCommittees[i]); + } + + tiebreakerCoreCommittee.addMembers(coreCommitteeMemberAddresses, tiebreakerConfig.quorum); + tiebreakerCoreCommittee.transferOwnership(address(adminExecutor)); + + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall(dualGovernance.setTiebreakerActivationTimeout, dgDeployConfig.tiebreakerActivationTimeout) + ); + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall(dualGovernance.setTiebreakerCommittee, address(tiebreakerCoreCommittee)) + ); + + for (uint256 i = 0; i < dgDeployConfig.sealableWithdrawalBlockers.length; ++i) { + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall( + dualGovernance.addTiebreakerSealableWithdrawalBlocker, dgDeployConfig.sealableWithdrawalBlockers[i] + ) + ); + } + } + + function configureDualGovernance( + Executor adminExecutor, + DualGovernance dualGovernance, + TiebreakerCoreCommittee tiebreakerCoreCommittee, + DualGovernanceContractDeployConfig.Context memory dgDeployConfig + ) internal { + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall(dualGovernance.registerProposer, (dgDeployConfig.adminProposer, address(adminExecutor))) + ); + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall(dualGovernance.setProposalsCanceller, dgDeployConfig.proposalsCanceller) + ); + adminExecutor.execute( + address(dualGovernance), + 0, + abi.encodeCall(dualGovernance.setResealCommittee, dgDeployConfig.resealCommittee) + ); + } + + function configureEmergencyProtectedTimelock( + Executor adminExecutor, + EmergencyProtectedTimelock timelock, + TimelockContractDeployConfig.Context memory timelockConfig + ) internal returns (TimelockedGovernance emergencyGovernance) { + if (timelockConfig.emergencyGovernanceProposer != address(0)) { + emergencyGovernance = + deployTimelockedGovernance({governance: timelockConfig.emergencyGovernanceProposer, timelock: timelock}); + adminExecutor.execute( + address(timelock), 0, abi.encodeCall(timelock.setEmergencyGovernance, (address(emergencyGovernance))) + ); + } + + if (timelockConfig.emergencyActivationCommittee != address(0)) { + console.log( + "Setting the emergency activation committee to %x...", timelockConfig.emergencyActivationCommittee + ); + adminExecutor.execute( + address(timelock), + 0, + abi.encodeCall( + timelock.setEmergencyProtectionActivationCommittee, (timelockConfig.emergencyActivationCommittee) + ) + ); + console.log("Emergency activation committee set successfully."); + } + + if (timelockConfig.emergencyExecutionCommittee != address(0)) { + console.log( + "Setting the emergency execution committee to %x...", timelockConfig.emergencyExecutionCommittee + ); + adminExecutor.execute( + address(timelock), + 0, + abi.encodeCall( + timelock.setEmergencyProtectionExecutionCommittee, (timelockConfig.emergencyExecutionCommittee) + ) + ); + console.log("Emergency execution committee set successfully."); + } + + if (timelockConfig.emergencyProtectionEndDate != Timestamps.ZERO) { + adminExecutor.execute( + address(timelock), + 0, + abi.encodeCall(timelock.setEmergencyProtectionEndDate, (timelockConfig.emergencyProtectionEndDate)) + ); + } + + if (timelockConfig.emergencyModeDuration != Durations.ZERO) { + adminExecutor.execute( + address(timelock), + 0, + abi.encodeCall(timelock.setEmergencyModeDuration, (timelockConfig.emergencyModeDuration)) + ); + } + } + + function finalizeEmergencyProtectedTimelockDeploy( + Executor adminExecutor, + EmergencyProtectedTimelock timelock, + address governance + ) internal { + adminExecutor.execute(address(timelock), 0, abi.encodeCall(timelock.setGovernance, (governance))); + adminExecutor.transferOwnership(address(timelock)); + } +} diff --git a/scripts/utils/deploy-files.sol b/scripts/utils/deploy-files.sol new file mode 100644 index 00000000..44907b33 --- /dev/null +++ b/scripts/utils/deploy-files.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {Vm} from "forge-std/Vm.sol"; + +// solhint-disable-next-line const-name-snakecase +Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + +library DeployFiles { + string internal constant DEPLOY_CONFIGS_DIR = "deploy-config"; + string internal constant DEPLOY_ARTIFACTS_DIR = "deploy-artifacts"; + + function resolveDeployConfig(string memory fileName) internal returns (string memory) { + if (bytes(fileName).length == 0) { + revert("fileName is empty"); + } + return string.concat(vm.projectRoot(), "/", DEPLOY_CONFIGS_DIR, "/", fileName); + } + + function resolveDeployArtifact(string memory fileName) internal returns (string memory) { + if (bytes(fileName).length == 0) { + revert("fileName is empty"); + } + return string.concat(vm.projectRoot(), "/", DEPLOY_ARTIFACTS_DIR, "/", fileName); + } +} diff --git a/test/regressions/dg-proposals-operations.t.sol b/test/regressions/dg-proposals-operations.t.sol new file mode 100644 index 00000000..c3877d65 --- /dev/null +++ b/test/regressions/dg-proposals-operations.t.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {EvmScriptUtils} from "../utils/evm-script-utils.sol"; +import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; + +import {ExternalCall, ExternalCallHelpers} from "../utils/executor-calls.sol"; +import {DGRegressionTestSetup, Proposers} from "../utils/integration-tests.sol"; + +import {ExecutableProposals} from "contracts/libraries/ExecutableProposals.sol"; + +import {LidoUtils, EvmScriptUtils} from "../utils/lido-utils.sol"; + +contract DGProposalOperationsTest is DGRegressionTestSetup { + using LidoUtils for LidoUtils.Context; + + function setUp() external { + _loadOrDeployDGSetup(); + } + + function testFork_ProposalLifecycle_HappyPathMultipleCalls() external { + ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(3); + + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" + ); + _assertProposalSubmitted(proposalId); + _assertSubmittedProposalData(proposalId, regularStaffCalls); + + _wait(_getAfterSubmitDelay().dividedBy(2)); + + // the min execution delay hasn't elapsed yet + vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); + this.external__scheduleProposal(proposalId); + + // wait till the first phase of timelock passes + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); + _assertProposalScheduled(proposalId); + + _wait(_getAfterScheduleDelay()); + + _assertCanExecute(proposalId, true); + _executeProposal(proposalId); + + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); + } + + function testFork_ProposalLifecycle_ExternalCallsWithValue() external { + uint256 ethValue = 3 ether; + + vm.deal(address(_getAdminExecutor()), ethValue); + uint256 adminExecutorValueBefore = address(_getAdminExecutor()).balance; + + ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); + regularStaffCalls[0].value = uint96(ethValue); + + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" + ); + _assertProposalSubmitted(proposalId); + _assertSubmittedProposalData(proposalId, regularStaffCalls); + + _wait(_getAfterSubmitDelay().dividedBy(2)); + + // the min execution delay hasn't elapsed yet + vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); + this.external__scheduleProposal(proposalId); + + // wait till the first phase of timelock passes + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); + _assertProposalScheduled(proposalId); + + _wait(_getAfterScheduleDelay()); + + _assertCanExecute(proposalId, true); + _executeProposal(proposalId); + + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); + + assertEq(address(_targetMock).balance, ethValue); + assertEq(adminExecutorValueBefore - ethValue, address(_getAdminExecutor()).balance); + } + + function testFork_ProposalLifecycle_AgentForwarding() external { + _grantAragonAgentExecuteRole(_timelock.getAdminExecutor()); + + uint256 ethPaymentValue = 1 ether; + vm.deal(address(_lido.agent), ethPaymentValue); + uint256 agentBalanceBefore = address(_lido.agent).balance; + + ExternalCall[] memory agentForwardingCalls = new ExternalCall[](2); + + agentForwardingCalls[0].target = address(_lido.agent); + agentForwardingCalls[0].payload = abi.encodeCall( + _lido.agent.execute, + (address(_targetMock), ethPaymentValue, abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (42))) + ); + + agentForwardingCalls[1].target = address(_lido.agent); + agentForwardingCalls[1].payload = abi.encodeCall( + _lido.agent.forward, + ( + EvmScriptUtils.encodeEvmCallScript( + address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doControversialStaff, ()) + ) + ) + ); + + uint256 proposalId = _submitProposalByAdminProposer(agentForwardingCalls, "Make calls via Agent forwarding"); + _assertProposalSubmitted(proposalId); + _assertSubmittedProposalData(proposalId, agentForwardingCalls); + + _wait(_getAfterSubmitDelay().dividedBy(2)); + + // the min execution delay hasn't elapsed yet + vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); + this.external__scheduleProposal(proposalId); + + // wait till the first phase of timelock passes + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); + _assertProposalScheduled(proposalId); + + _wait(_getAfterScheduleDelay()); + + _assertCanExecute(proposalId, true); + _executeProposal(proposalId); + + ExternalCall[] memory expectedTargetMockCalls = new ExternalCall[](2); + + expectedTargetMockCalls[0].value = uint96(ethPaymentValue); + expectedTargetMockCalls[0].payload = abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (42)); + + expectedTargetMockCalls[1].value = 0; + expectedTargetMockCalls[1].payload = abi.encodeCall(IPotentiallyDangerousContract.doControversialStaff, ()); + + _assertTargetMockCalls(address(_lido.agent), expectedTargetMockCalls); + assertEq(address(_targetMock).balance, ethPaymentValue); + assertEq(agentBalanceBefore - ethPaymentValue, address(_lido.agent).balance); + } + + function testFork_AragonVotingAsProposer() external { + assertTrue( + _dgDeployedContracts.dualGovernance.isProposer(address(_lido.voting)), "Aragon Voting is not DG proposer" + ); + + Proposers.Proposer memory votingProposer = + _dgDeployedContracts.dualGovernance.getProposer(address(_lido.voting)); + + assertTrue(_dgDeployedContracts.dualGovernance.isExecutor(votingProposer.executor)); + + uint256 proposalId; + ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); + _step("1. Aragon Vote may be used to submit proposal"); + { + uint256 dgProposalsCountBefore = _timelock.getProposalsCount(); + bytes memory voteWithProposalSubmission = EvmScriptUtils.encodeEvmCallScript( + address(_dgDeployedContracts.dualGovernance), + abi.encodeCall( + _dgDeployedContracts.dualGovernance.submitProposal, + (regularStaffCalls, "Proposal submitted by the DAO") + ) + ); + + uint256 voteId = _lido.adoptVote("Submit DG proposal", voteWithProposalSubmission); + _lido.executeVote(voteId); + + assertEq(_timelock.getProposalsCount(), dgProposalsCountBefore + 1); + + proposalId = _getLastProposalId(); + + _assertProposalSubmitted(proposalId); + _assertSubmittedProposalData(proposalId, regularStaffCalls); + } + + _step("2. Proposal may be scheduled and executed"); + { + // wait till the first phase of timelock passes + _wait(_getAfterSubmitDelay()); + + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); + _assertProposalScheduled(proposalId); + + _wait(_getAfterScheduleDelay()); + + _assertCanExecute(proposalId, true); + _executeProposal(proposalId); + + _assertTargetMockCalls(votingProposer.executor, regularStaffCalls); + } + } + + function testFork_ProposalLifecycle_ProposalCancellation() external { + vm.skip(true); + } +} diff --git a/test/regressions/emergency-protection.t.sol b/test/regressions/emergency-protection.t.sol new file mode 100644 index 00000000..7a99bb97 --- /dev/null +++ b/test/regressions/emergency-protection.t.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {DGRegressionTestSetup, ExternalCall, ExternalCallHelpers} from "../utils/integration-tests.sol"; + +import {ITiebreaker} from "contracts/interfaces/ITiebreaker.sol"; +import {EmergencyProtection} from "contracts/libraries/EmergencyProtection.sol"; + +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; +import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; + +contract EmergencyProtectionRegressionTest is DGRegressionTestSetup { + function setUp() external { + _loadOrDeployDGSetup(); + } + + function testFork_EmergencyReset() external { + ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); + + uint256 proposalId; + _step("1. The proposal is submitted"); + { + proposalId = + _submitProposalByAdminProposer(regularStaffCalls, "Propose to doSmth on target passing dual governance"); + _assertSubmittedProposalData(proposalId, regularStaffCalls); + + // proposal can't be scheduled until the AFTER_SUBMIT_DELAY has passed + _assertCanSchedule(proposalId, false); + } + + _step("2. The proposal is scheduled"); + { + // wait until the delay has passed + _wait(_getAfterSubmitDelay().plusSeconds(1)); + + // when the first delay is passed and the is no opposition from the stETH holders + // the proposal can be scheduled + _assertCanSchedule(proposalId, true); + + _scheduleProposal(proposalId); + + // proposal can't be executed until the second delay has ended + _assertProposalScheduled(proposalId); + _assertCanExecute(proposalId, false); + } + + _step("3. Emergency mode activated & governance reset"); + { + // some time passes and emergency committee activates emergency mode + // and resets the controller + _wait(_getAfterScheduleDelay().dividedBy(2)); + + // committee resets governance + _activateEmergencyMode(); + _emergencyReset(); + + // proposal is canceled now + _wait(_getAfterScheduleDelay().dividedBy(2).plusSeconds(1)); + + // remove canceled call from the timelock + _assertCanExecute(proposalId, false); + _assertProposalCancelled(proposalId); + } + } + + function testFork_EmergencyProtectionExpiration() external { + _step("1. DAO operates regularly"); + { + _adoptProposalByAdminProposer(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); + } + + _step("2. Emergency protection expires"); + { + if (_isEmergencyProtectionEnabled()) { + _wait(_getEmergencyProtectionDuration().plusSeconds(1)); + } + assertFalse(_isEmergencyProtectionEnabled()); + } + + _step("3. Emergency activation committee has not power"); + { + vm.expectRevert( + abi.encodeWithSelector( + EmergencyProtection.EmergencyProtectionExpired.selector, + _getEmergencyProtectionEndsAfter().toSeconds() + ) + ); + this.external__activateEmergencyMode(); + } + + _step("4. DAO operated as usually when emergency protection expired"); + { + _adoptProposalByAdminProposer(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); + } + } +} diff --git a/test/regressions/tiebreaker.t.sol b/test/regressions/tiebreaker.t.sol new file mode 100644 index 00000000..e2614e42 --- /dev/null +++ b/test/regressions/tiebreaker.t.sol @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {DGRegressionTestSetup, PercentsD16, ExternalCall} from "../utils/integration-tests.sol"; + +import {ISealable} from "../utils/interfaces/ISealable.sol"; +import {ITiebreaker} from "contracts/interfaces/ITiebreaker.sol"; + +import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; +import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; + +contract TiebreakerRegressionTest is DGRegressionTestSetup { + address internal immutable _VETOER = makeAddr("VETOER"); + uint256 public constant PAUSE_INFINITELY = type(uint256).max; + + function setUp() external { + _loadOrDeployDGSetup(); + _setupStETHBalance(_VETOER, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); + } + + function testFork_ProposalApproval_TiebreakerActivationTimeout() external { + ITiebreaker.TiebreakerDetails memory details = _dgDeployedContracts.dualGovernance.getTiebreakerDetails(); + + _step("1. Tiebreaker activation"); + { + _assertNormalState(); + + _lockStETH(_VETOER, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(50)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); + + _activateNextState(); + _assertRageQuitState(); + + _wait(details.tiebreakerActivationTimeout); + _activateNextState(); + } + + _step("2. Proposal is submitted by the DAO to execute by Tiebreaker"); + uint256 proposalIdToExecute; + ExternalCall[] memory proposalCalls; + { + proposalCalls = _getMockTargetRegularStaffCalls(2); + proposalIdToExecute = _submitProposalByAdminProposer(proposalCalls, "Proposal for execution"); + } + + _step("3. Tiebreaker votes to execute the proposal"); + { + uint256 quorum; + uint256 support; + bool isExecuted; + TiebreakerCoreCommittee coreTiebreaker = TiebreakerCoreCommittee(details.tiebreakerCommittee); + address[] memory subTiebreakers = coreTiebreaker.getMembers(); + + for (uint256 i = 0; i < coreTiebreaker.getQuorum(); ++i) { + TiebreakerSubCommittee subTiebreaker = TiebreakerSubCommittee(subTiebreakers[i]); + + _executeScheduleProposalBySubCommittee(TiebreakerSubCommittee(subTiebreakers[i]), proposalIdToExecute); + + (support, quorum, /* quorumAt */, isExecuted) = + coreTiebreaker.getScheduleProposalState(proposalIdToExecute); + + assertFalse(isExecuted); + assertEq(support, i + 1); + } + assertEq(support, quorum); + + // Waiting for submit delay pass + _wait(coreTiebreaker.getTimelockDuration()); + + coreTiebreaker.executeScheduleProposal(proposalIdToExecute); + } + + _step("4. Proposal may be scheduled and executed now"); + { + _assertProposalScheduled(proposalIdToExecute); + + _wait(_getAfterScheduleDelay()); + + _executeProposal(proposalIdToExecute); + _assertProposalExecuted(proposalIdToExecute); + _assertTargetMockCalls(_getAdminExecutor(), proposalCalls); + } + } + + function testFork_ResumeWithdrawals() external { + ITiebreaker.TiebreakerDetails memory details = _dgDeployedContracts.dualGovernance.getTiebreakerDetails(); + + address[] memory sealableWithdrawalBlockers = _getSealableWithdrawalBlockers(); + _step("1. Validate that sealable withdrawal blockers not empty"); + { + assertTrue(sealableWithdrawalBlockers.length > 0); + } + + _step("2. Pause sealable withdrawal blockers manually"); + + ISealable pausedSealable = ISealable(sealableWithdrawalBlockers[0]); + if (!pausedSealable.isPaused()) { + vm.startPrank(address(_dgDeployedContracts.resealManager)); + pausedSealable.pauseFor(pausedSealable.PAUSE_INFINITELY()); + vm.stopPrank(); + assertTrue(pausedSealable.isPaused()); + } + + // Tiebreak activation + _step("3. Rage Quit state is entered"); + { + _assertNormalState(); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); + _activateNextState(); + _assertRageQuitState(); + _wait(_dgDeployedContracts.dualGovernance.getTiebreakerDetails().tiebreakerActivationTimeout); + _activateNextState(); + } + + _step("4. Tiebreaker votes to resume paused sealable"); + { + uint256 quorum; + uint256 support; + bool isExecuted; + TiebreakerCoreCommittee coreTiebreaker = TiebreakerCoreCommittee(details.tiebreakerCommittee); + address[] memory subTiebreakers = coreTiebreaker.getMembers(); + + for (uint256 i = 0; i < coreTiebreaker.getQuorum(); ++i) { + TiebreakerSubCommittee subTiebreaker = TiebreakerSubCommittee(subTiebreakers[i]); + + _executeResumeProposalBySubCommittee(TiebreakerSubCommittee(subTiebreakers[i]), address(pausedSealable)); + + (support, quorum, /* quorumAt */, isExecuted) = coreTiebreaker.getSealableResumeState( + address(pausedSealable), coreTiebreaker.getSealableResumeNonce(address(pausedSealable)) + ); + + assertFalse(isExecuted); + assertEq(support, i + 1); + } + assertEq(support, quorum); + + // Waiting for submit delay pass + _wait(coreTiebreaker.getTimelockDuration()); + + coreTiebreaker.executeSealableResume(address(pausedSealable)); + } + + _step("5. Sealable is resumed and rage quit may be finalized"); + { + assertFalse(pausedSealable.isPaused()); + } + } + + function _executeScheduleProposalBySubCommittee( + TiebreakerSubCommittee subTiebreaker, + uint256 proposalIdToExecute + ) internal { + uint256 subTiebreakerQuorum = subTiebreaker.getQuorum(); + address[] memory subTiebreakerMembers = subTiebreaker.getMembers(); + + for (uint256 j = 0; j < subTiebreakerQuorum; ++j) { + vm.prank(subTiebreakerMembers[j]); + subTiebreaker.scheduleProposal(proposalIdToExecute); + (uint256 support, uint256 quorum, /* quorumAt */, bool isExecuted) = + subTiebreaker.getScheduleProposalState(proposalIdToExecute); + assertEq(support, j + 1); + assertFalse(isExecuted); + } + _wait(subTiebreaker.getTimelockDuration()); + subTiebreaker.executeScheduleProposal(proposalIdToExecute); + + (uint256 support, uint256 quorum, /* quorumAt */, bool isExecuted) = + subTiebreaker.getScheduleProposalState(proposalIdToExecute); + assertEq(support, quorum); + assertTrue(isExecuted); + } + + function _executeResumeProposalBySubCommittee( + TiebreakerSubCommittee subTiebreaker, + address sealableToUnpause + ) internal { + uint256 subTiebreakerQuorum = subTiebreaker.getQuorum(); + address[] memory subTiebreakerMembers = subTiebreaker.getMembers(); + + for (uint256 j = 0; j < subTiebreakerQuorum; ++j) { + vm.prank(subTiebreakerMembers[j]); + subTiebreaker.sealableResume(sealableToUnpause); + (uint256 support, uint256 quorum, /* quorumAt */, bool isExecuted) = + subTiebreaker.getSealableResumeState(sealableToUnpause); + assertEq(support, j + 1); + assertFalse(isExecuted); + } + _wait(subTiebreaker.getTimelockDuration()); + subTiebreaker.executeSealableResume(sealableToUnpause); + + (uint256 support, uint256 quorum, /* quorumAt */, bool isExecuted) = + subTiebreaker.getSealableResumeState(sealableToUnpause); + assertEq(support, quorum); + assertTrue(isExecuted); + } +} diff --git a/test/scenario/time-sensitive-proposal-execution.t.sol b/test/regressions/time-sensitive-proposal-execution.t.sol similarity index 73% rename from test/scenario/time-sensitive-proposal-execution.t.sol rename to test/regressions/time-sensitive-proposal-execution.t.sol index e5e5e64b..76d92bf7 100644 --- a/test/scenario/time-sensitive-proposal-execution.t.sol +++ b/test/regressions/time-sensitive-proposal-execution.t.sol @@ -6,21 +6,22 @@ import {Timestamps, Timestamp} from "contracts/types/Timestamp.sol"; import {TimeConstraints} from "../utils/time-constraints.sol"; import {ExternalCall, ExternalCallHelpers} from "../utils/executor-calls.sol"; -import {ScenarioTestBlueprint, LidoUtils, console} from "../utils/scenario-test-blueprint.sol"; +import {DGRegressionTestSetup} from "../utils/integration-tests.sol"; interface ITimeSensitiveContract { function timeSensitiveMethod() external; } -contract ScheduledProposalExecution is ScenarioTestBlueprint { - TimeConstraints private immutable _TIME_CONSTRAINTS = new TimeConstraints(); +contract TimeSensitiveProposalsRegressionTest is DGRegressionTestSetup { + TimeConstraints internal _timelockConstraints; Duration private immutable _EXECUTION_DELAY = Durations.from(30 days); // Proposal may be executed not earlier than the 30 days from launch Duration private immutable _EXECUTION_START_DAY_TIME = Durations.from(4 hours); // And at time frame starting from the 4:00 UTC Duration private immutable _EXECUTION_END_DAY_TIME = Durations.from(12 hours); // till the 12:00 UTC function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _loadOrDeployDGSetup(); + _timelockConstraints = new TimeConstraints(); } function testFork_TimeFrameProposalExecution() external { @@ -30,15 +31,15 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { ExternalCall[] memory scheduledProposalCalls = ExternalCallHelpers.create( [ ExternalCall({ - target: address(_TIME_CONSTRAINTS), + target: address(_timelockConstraints), value: 0 wei, - payload: abi.encodeCall(_TIME_CONSTRAINTS.checkExecuteAfterTimestamp, (executableAfter)) + payload: abi.encodeCall(_timelockConstraints.checkExecuteAfterTimestamp, (executableAfter)) }), ExternalCall({ - target: address(_TIME_CONSTRAINTS), + target: address(_timelockConstraints), value: 0 wei, payload: abi.encodeCall( - _TIME_CONSTRAINTS.checkExecuteWithinDayTime, (_EXECUTION_START_DAY_TIME, _EXECUTION_END_DAY_TIME) + _timelockConstraints.checkExecuteWithinDayTime, (_EXECUTION_START_DAY_TIME, _EXECUTION_END_DAY_TIME) ) }), ExternalCall({ @@ -53,7 +54,7 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { _step("1. Submit time sensitive proposal"); { proposalId = - _submitProposal(_dualGovernance, "DAO performs some time sensitive action", scheduledProposalCalls); + _submitProposalByAdminProposer(scheduledProposalCalls, "DAO performs some time sensitive action"); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, scheduledProposalCalls); @@ -62,14 +63,14 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { _step("2. Wait while the DG timelock has passed & schedule proposal"); { _wait(_timelock.getAfterSubmitDelay().plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); } _step("3. Proposal can't be executed earlier than specified date"); { - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); assertTrue(Timestamps.now() < executableAfter); @@ -87,20 +88,20 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { _step("5. Adjust current day time of the node to 00:00 UTC"); { // adjust current time to 00:00 UTC - _wait(_TIME_CONSTRAINTS.DAY_DURATION() - _TIME_CONSTRAINTS.getCurrentDayTime()); - assertEq(_TIME_CONSTRAINTS.getCurrentDayTime(), Durations.ZERO); + _wait(_timelockConstraints.DAY_DURATION() - _timelockConstraints.getCurrentDayTime()); + assertEq(_timelockConstraints.getCurrentDayTime(), Durations.ZERO); midnightSnapshotId = vm.snapshot(); } _step("6.a. Execution reverts when current time is less than allowed range"); { - assertTrue(_TIME_CONSTRAINTS.getCurrentDayTime() < _EXECUTION_START_DAY_TIME); + assertTrue(_timelockConstraints.getCurrentDayTime() < _EXECUTION_START_DAY_TIME); vm.expectRevert( abi.encodeWithSelector( TimeConstraints.DayTimeOutOfRange.selector, - _TIME_CONSTRAINTS.getCurrentDayTime(), + _timelockConstraints.getCurrentDayTime(), _EXECUTION_START_DAY_TIME, _EXECUTION_END_DAY_TIME ) @@ -112,12 +113,12 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { _step("6.b. Execution reverts when current time is greater than allowed range"); { _wait(_EXECUTION_END_DAY_TIME.plusSeconds(1)); - assertTrue(_TIME_CONSTRAINTS.getCurrentDayTime() > _EXECUTION_END_DAY_TIME); + assertTrue(_timelockConstraints.getCurrentDayTime() > _EXECUTION_END_DAY_TIME); vm.expectRevert( abi.encodeWithSelector( TimeConstraints.DayTimeOutOfRange.selector, - _TIME_CONSTRAINTS.getCurrentDayTime(), + _timelockConstraints.getCurrentDayTime(), _EXECUTION_START_DAY_TIME, _EXECUTION_END_DAY_TIME ) @@ -132,8 +133,8 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { { _wait(_EXECUTION_START_DAY_TIME); assertTrue( - _TIME_CONSTRAINTS.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME - && _TIME_CONSTRAINTS.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME + _timelockConstraints.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME + && _timelockConstraints.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME ); _executeProposal(proposalId); @@ -145,8 +146,8 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { { _wait(_EXECUTION_END_DAY_TIME); assertTrue( - _TIME_CONSTRAINTS.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME - && _TIME_CONSTRAINTS.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME + _timelockConstraints.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME + && _timelockConstraints.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME ); _executeProposal(proposalId); @@ -158,8 +159,8 @@ contract ScheduledProposalExecution is ScenarioTestBlueprint { { _wait((_EXECUTION_END_DAY_TIME - _EXECUTION_START_DAY_TIME).dividedBy(2)); assertTrue( - _TIME_CONSTRAINTS.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME - && _TIME_CONSTRAINTS.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME + _timelockConstraints.getCurrentDayTime() >= _EXECUTION_START_DAY_TIME + && _timelockConstraints.getCurrentDayTime() <= _EXECUTION_END_DAY_TIME ); _executeProposal(proposalId); diff --git a/test/scenario/agent-timelock.t.sol b/test/scenario/agent-timelock.t.sol index e74756cb..15b4ef52 100644 --- a/test/scenario/agent-timelock.t.sol +++ b/test/scenario/agent-timelock.t.sol @@ -1,70 +1,49 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import {Proposers} from "contracts/libraries/Proposers.sol"; - -import {ExternalCall, ExternalCallHelpers, ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; -import {LidoUtils} from "../utils/lido-utils.sol"; +import {DGScenarioTestSetup, ExternalCallHelpers, ExternalCall, Proposers} from "../utils/integration-tests.sol"; interface IRegularContract { function regularMethod() external; } -contract AgentTimelockTest is ScenarioTestBlueprint { - using LidoUtils for LidoUtils.Context; - +contract AragonAgentAsExecutorScenarioTest is DGScenarioTestSetup { function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); + _deployDGSetup({isEmergencyProtectionEnabled: true}); } function testFork_AragonAgentAsExecutor_HappyPath() external { - _step("0. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); + _step("1. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); { - _grantAgentExecutorRoleToTimelock(); + _grantAragonAgentExecuteRole(address(_timelock)); } address agentProposer = makeAddr("AGENT_PROPOSER"); - _step("1. Submit proposal to register Aragon as the executor"); + _step("2. Submit proposal to register Aragon Agent as the executor"); { _addAragonAgentProposer(agentProposer); } ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - - uint256 agentActionsProposalId; - _step("2. Submit proposal via the Agent proposer"); + _step("3. Adopt the proposal with the actions executed by the Aragon Agent executor"); { - vm.prank(agentProposer); - agentActionsProposalId = - _dualGovernance.submitProposal(regularStaffCalls, "Make regular staff using Agent as executor"); - - _assertSubmittedProposalData(agentActionsProposalId, address(_lido.agent), regularStaffCalls); + _adoptProposal(agentProposer, regularStaffCalls, "Make regular staff using Agent as executor"); } - _step("3. Execute the proposal"); + _step("4. Validate action was executed by the Agent"); { - _assertProposalSubmitted(agentActionsProposalId); - _waitAfterSubmitDelayPassed(); - - _scheduleProposalViaDualGovernance(agentActionsProposalId); - _assertProposalScheduled(agentActionsProposalId); - - _waitAfterScheduleDelayPassed(); - _executeProposal(agentActionsProposalId); - _assertProposalExecuted(agentActionsProposalId); - - _assertTargetMockCalls(address(_lido.agent), regularStaffCalls); + _assertTargetMockCalls({caller: address(_lido.agent), calls: regularStaffCalls}); } } function testFork_AragonAgentAsExecutor_RevertOn_FailedCall() external { - _step("0. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); + _step("1. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); { - _grantAgentExecutorRoleToTimelock(); + _grantAragonAgentExecuteRole(address(_timelock)); } address agentProposer = makeAddr("AGENT_PROPOSER"); - _step("1. Submit proposal to register Aragon as the executor"); + _step("2. Submit proposal to register Aragon as the executor"); { _addAragonAgentProposer(agentProposer); } @@ -73,24 +52,24 @@ contract AgentTimelockTest is ScenarioTestBlueprint { vm.mockCallRevert(regularStaffCalls[0].target, regularStaffCalls[0].payload, "INVALID TARGET"); uint256 agentActionsProposalId; - _step("2. Submit proposal which should revert via the Agent proposer"); + _step("3. Submit proposal which should revert via the Agent proposer"); { vm.prank(agentProposer); agentActionsProposalId = - _dualGovernance.submitProposal(regularStaffCalls, "Make regular staff using Agent as executor"); + _submitProposal(agentProposer, regularStaffCalls, "Make regular staff using Agent as executor"); _assertSubmittedProposalData(agentActionsProposalId, address(_lido.agent), regularStaffCalls); } - _step("3. The execution of the proposal fails"); + _step("4. The execution of the proposal fails"); { _assertProposalSubmitted(agentActionsProposalId); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _scheduleProposalViaDualGovernance(agentActionsProposalId); + _scheduleProposal(agentActionsProposalId); _assertProposalScheduled(agentActionsProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); vm.expectRevert("INVALID TARGET"); _executeProposal(agentActionsProposalId); @@ -100,13 +79,13 @@ contract AgentTimelockTest is ScenarioTestBlueprint { } function testFork_AgentAsExecutor_SucceedOnEmptyAccountCalls() external { - _step("0. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); + _step("1. Grant EXECUTE_ROLE permission to the timelock on the Agent contract"); { - _grantAgentExecutorRoleToTimelock(); + _grantAragonAgentExecuteRole(address(_timelock)); } address agentProposer = makeAddr("AGENT_PROPOSER"); - _step("1. Submit proposal to register Aragon as the executor"); + _step("2. Submit proposal to register Aragon as the executor"); { _addAragonAgentProposer(agentProposer); } @@ -128,170 +107,43 @@ contract AgentTimelockTest is ScenarioTestBlueprint { vm.deal(address(_lido.agent), agentBalanceBefore + callValue); uint256 agentActionsProposalId; - _step("2. Submit proposal via the Agent proposer"); - { - vm.prank(agentProposer); - agentActionsProposalId = - _dualGovernance.submitProposal(callsToEmptyAccount, "Make different calls to EOA account"); - _assertSubmittedProposalData(agentActionsProposalId, address(_lido.agent), callsToEmptyAccount); + _step("3. Adopt proposal via the Agent proposer with calls to EOA account"); + { + _adoptProposal(agentProposer, callsToEmptyAccount, "Make different calls to EOA account"); } - _step("3. Execute the proposal"); + _step("4. When the calls is done by Agent, it's not failed and executed successfully"); { - _assertProposalSubmitted(agentActionsProposalId); - _waitAfterSubmitDelayPassed(); - - _scheduleProposalViaDualGovernance(agentActionsProposalId); - _assertProposalScheduled(agentActionsProposalId); - - _waitAfterScheduleDelayPassed(); - _executeProposal(agentActionsProposalId); - _assertProposalExecuted(agentActionsProposalId); - assertEq(nonContractAccount.balance, 1 ether); assertEq(address(_lido.agent).balance, agentBalanceBefore); } } - function testFork_AgentTimelockHappyPath() external { - ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - - uint256 proposalId; - _step("1. THE PROPOSAL IS SUBMITTED"); - { - proposalId = _submitProposalViaDualGovernance( - "Propose to doSmth on target passing dual governance", regularStaffCalls - ); - - _assertSubmittedProposalData(proposalId, _getAdminExecutor(), regularStaffCalls); - _assertCanScheduleViaDualGovernance(proposalId, false); - } - - _step("2. THE PROPOSAL IS SCHEDULED"); - { - _waitAfterSubmitDelayPassed(); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); - - _assertProposalScheduled(proposalId); - _assertCanExecute(proposalId, false); - } - - _step("3. THE PROPOSAL CAN BE EXECUTED"); - { - // wait until the second delay has passed - _waitAfterScheduleDelayPassed(); - - // Now proposal can be executed - _assertCanExecute(proposalId, true); - - _assertNoTargetMockCalls(); - - _executeProposal(proposalId); - _assertProposalExecuted(proposalId); - - _assertCanExecute(proposalId, false); - _assertCanScheduleViaDualGovernance(proposalId, false); - - _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); - } - } - - function testFork_TimelockEmergencyReset() external { - ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - - // --- - // 1. THE PROPOSAL IS SUBMITTED - // --- - uint256 proposalId; - { - proposalId = _submitProposalViaDualGovernance( - "Propose to doSmth on target passing dual governance", regularStaffCalls - ); - _assertSubmittedProposalData(proposalId, _getAdminExecutor(), regularStaffCalls); - - // proposal can't be scheduled until the AFTER_SUBMIT_DELAY has passed - _assertCanScheduleViaDualGovernance(proposalId, false); - } - - // --- - // 2. THE PROPOSAL IS SCHEDULED - // --- - { - // wait until the delay has passed - _wait(_timelock.getAfterSubmitDelay().plusSeconds(1)); - - // when the first delay is passed and the is no opposition from the stETH holders - // the proposal can be scheduled - _assertCanScheduleViaDualGovernance(proposalId, true); - - _scheduleProposalViaDualGovernance(proposalId); - - // proposal can't be executed until the second delay has ended - _assertProposalScheduled(proposalId); - _assertCanExecute(proposalId, false); - } - - // --- - // 3. EMERGENCY MODE ACTIVATED & GOVERNANCE RESET - // --- - { - // some time passes and emergency committee activates emergency mode - // and resets the controller - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - - // committee resets governance - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - vm.prank(address(_emergencyExecutionCommittee)); - _timelock.emergencyReset(); - - // proposal is canceled now - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - - // remove canceled call from the timelock - _assertCanExecute(proposalId, false); - _assertProposalCancelled(proposalId); - } - } - // --- // Helper Methods // --- - function _grantAgentExecutorRoleToTimelock() internal { - _lido.grantPermission(address(_lido.agent), _lido.agent.EXECUTE_ROLE(), address(_timelock)); - assertTrue(_lido.acl.hasPermission(address(_timelock), address(_lido.agent), _lido.agent.EXECUTE_ROLE())); - } - function _addAragonAgentProposer(address agentProposer) internal { ExternalCall[] memory externalCalls = ExternalCallHelpers.create( [ ExternalCall({ value: 0, - target: address(_dualGovernance), - payload: abi.encodeCall(_dualGovernance.registerProposer, (agentProposer, address(_lido.agent))) + target: address(_dgDeployedContracts.dualGovernance), + payload: abi.encodeCall( + _dgDeployedContracts.dualGovernance.registerProposer, (agentProposer, address(_lido.agent)) + ) }) ] ); - uint256 addAgentProposerProposalId = - _submitProposalViaDualGovernance("Add Aragon Agent as proposer to the Dual Governance", externalCalls); - - _assertProposalSubmitted(addAgentProposerProposalId); - _waitAfterSubmitDelayPassed(); - _scheduleProposalViaDualGovernance(addAgentProposerProposalId); - _assertProposalScheduled(addAgentProposerProposalId); + uint256 proposersCountBefore = _getProposers().length; - _waitAfterScheduleDelayPassed(); - _executeProposal(addAgentProposerProposalId); - _assertProposalExecuted(addAgentProposerProposalId); + _adoptProposalByAdminProposer(externalCalls, "Add Aragon Agent as proposer to the Dual Governance"); - Proposers.Proposer[] memory proposers = _dualGovernance.getProposers(); + Proposers.Proposer[] memory proposers = _getProposers(); - assertEq(proposers.length, 2); + assertEq(proposers.length, proposersCountBefore + 1); assertEq(proposers[1].account, agentProposer); assertEq(proposers[1].executor, address(_lido.agent)); } diff --git a/test/scenario/dg-launch-scenarios.t.sol b/test/scenario/dg-launch-scenarios.t.sol new file mode 100644 index 00000000..fb0e5a51 --- /dev/null +++ b/test/scenario/dg-launch-scenarios.t.sol @@ -0,0 +1,479 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; +/* solhint-disable no-console */ + +import {console} from "forge-std/console.sol"; + +import { + LidoUtils, + DGScenarioTestSetup, + ExternalCallHelpers, + ExternalCall, + Proposers, + IGovernance +} from "../utils/integration-tests.sol"; +import {TimelockedGovernance, ContractsDeployment} from "scripts/utils/contracts-deployment.sol"; + +import {Durations} from "contracts/types/Duration.sol"; +import {Timestamps, Timestamp} from "contracts/types/Timestamp.sol"; + +import {DeployVerification} from "scripts/utils/DeployVerification.sol"; + +import {EvmScriptUtils} from "../utils/evm-script-utils.sol"; +import {DGSetupDeployArtifacts} from "scripts/utils/contracts-deployment.sol"; + +contract DGLaunchStrategiesScenarioTest is DGScenarioTestSetup { + using LidoUtils for LidoUtils.Context; + + address internal immutable _TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER = + makeAddr("TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER"); + + TimelockedGovernance internal _emergencyGovernance; + DGSetupDeployArtifacts.Context internal _deployArtifact; + + function setUp() external { + _deployArtifact.deployConfig = _dgDeployConfig; + _deployArtifact.deployedContracts = _dgDeployedContracts; + } + + function testFork_DualGovernance_DeploymentWithDryRunTemporaryGovernance() external { + _step("0. Deploy DG contracts with temporary emergency governance for dry-run test"); + { + _deployDGSetup({emergencyGovernanceProposer: _TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER}); + _emergencyGovernance = + ContractsDeployment.deployTimelockedGovernance({governance: address(_lido.voting), timelock: _timelock}); + } + + _step("1. Verify the state of the DG setup before the dry-run emergency reset"); + { + DeployVerification.verify(_deployArtifact); + } + + _step("2. Activate Dual Governance Emergency Mode"); + { + _activateEmergencyMode(); + } + + _step("3. Temporary Emergency Governance Proposer makes dry-run governance reset"); + { + _emergencyReset(); + } + + _step( + string.concat( + "4. Prepare calls to set Governance, Activation Committee, ", + "Execution Committee, Emergency Mode End Date and Emergency Mode Duration" + ) + ); + ExternalCall[] memory finalizeDGSetupCalls; + { + Timestamp emergencyProtectionEndDate = Durations.from(90 days).addTo(Timestamps.now()); + + finalizeDGSetupCalls = ExternalCallHelpers.create( + address(_timelock), + [ + abi.encodeCall(_timelock.setGovernance, (address(_dgDeployedContracts.dualGovernance))), + abi.encodeCall(_timelock.setEmergencyGovernance, address(_emergencyGovernance)), + abi.encodeCall( + _timelock.setEmergencyProtectionActivationCommittee, (_DEFAULT_EMERGENCY_ACTIVATION_COMMITTEE) + ), + abi.encodeCall( + _timelock.setEmergencyProtectionExecutionCommittee, (_DEFAULT_EMERGENCY_EXECUTION_COMMITTEE) + ), + abi.encodeCall(_timelock.setEmergencyProtectionEndDate, (emergencyProtectionEndDate)), + abi.encodeCall(_timelock.setEmergencyModeDuration, (Durations.from(180 days))) + ] + ); + console.log("Calls to set DG state:"); + console.logBytes(abi.encode(finalizeDGSetupCalls)); + } + + _step("5. Submit proposal from the temporary governance to configure timelock for the launch"); + { + _adoptProposal( + _TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER, finalizeDGSetupCalls, "Dual Governance after dry-run setup" + ); + console.log("Last Proposal Id: %d", _getLastProposalId()); + } + + _step("6. Verify the state of the DG setup after update and before voting start"); + { + _dgDeployedContracts.emergencyGovernance = _emergencyGovernance; + _dgDeployConfig.timelock.emergencyGovernanceProposer = address(_lido.voting); + + DeployVerification.verify(_deployArtifact); + } + + _step("7. Prepare Roles Verifier"); + MockRolesVerifier rolesVerifier; + MockDGStateVerifier dgStateVerifier; + { + rolesVerifier = new MockRolesVerifier(); + dgStateVerifier = new MockDGStateVerifier(); + } + + _step("7. Activate Dual Governance with DAO Voting"); + { + EvmScriptUtils.EvmScriptCall[] memory agentForwardCalls = new EvmScriptUtils.EvmScriptCall[](2); + + // Grant PAUSE_ROLE to ResealManager + agentForwardCalls[0].target = address(_lido.withdrawalQueue); + agentForwardCalls[0].data = abi.encodeCall( + _lido.withdrawalQueue.grantRole, + (_lido.withdrawalQueue.PAUSE_ROLE(), address(_dgDeployedContracts.resealManager)) + ); + + // Grant RESUME_ROLE to ResealManager + agentForwardCalls[1].target = address(_lido.withdrawalQueue); + agentForwardCalls[1].data = abi.encodeCall( + _lido.withdrawalQueue.grantRole, + (_lido.withdrawalQueue.RESUME_ROLE(), address(_dgDeployedContracts.resealManager)) + ); + + EvmScriptUtils.EvmScriptCall[] memory aragonVoteCalls = new EvmScriptUtils.EvmScriptCall[](6); + + // Grant RUN_SCRIPT_ROLE to AdminExecutor + aragonVoteCalls[0].target = address(_lido.acl); + aragonVoteCalls[0].data = abi.encodeCall( + _lido.acl.grantPermission, + (address(_getAdminExecutor()), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + // Grant EXECUTE_ROLE to AdminExecutor + aragonVoteCalls[1].target = address(_lido.acl); + aragonVoteCalls[1].data = abi.encodeCall( + _lido.acl.grantPermission, + (address(_getAdminExecutor()), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + + // Transfer RUN_SCRIPT_ROLE manager to Agent + aragonVoteCalls[2].target = address(_lido.acl); + aragonVoteCalls[2].data = abi.encodeCall( + _lido.acl.setPermissionManager, + (address(_lido.agent), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + // Transfer EXECUTE_ROLE manager to Agent + aragonVoteCalls[3].target = address(_lido.acl); + aragonVoteCalls[3].data = abi.encodeCall( + _lido.acl.setPermissionManager, (address(_lido.agent), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + + ExternalCall[] memory dgLaunchCalls = ExternalCallHelpers.create( + [ + ExternalCall({ + target: address(_lido.agent), + value: 0, + payload: abi.encodeCall( + _lido.agent.forward, + ( + EvmScriptUtils.encodeEvmCallScript( + address(_lido.acl), + abi.encodeCall( + _lido.acl.revokePermission, + (address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ) + ) + ) + ) + }), + ExternalCall({ + target: address(dgStateVerifier), + value: 0, + payload: abi.encodeCall( + dgStateVerifier.validate, + (address(_dgDeployedContracts.dualGovernance), address(_dgDeployedContracts.timelock)) + ) + }) + ] + ); + + aragonVoteCalls[4].target = address(rolesVerifier); + aragonVoteCalls[4].data = abi.encodeCall( + rolesVerifier.validate, + (address(_dgDeployedContracts.adminExecutor), address(_dgDeployedContracts.resealManager)) + ); + + // submit proposal into DG to revoke Agent.RUN_SCRIPT_ROLE from voting + aragonVoteCalls[5].target = address(_dgDeployedContracts.dualGovernance); + aragonVoteCalls[5].data = + abi.encodeCall(_dgDeployedContracts.dualGovernance.submitProposal, (dgLaunchCalls, "Finally Launch DG")); + + uint256 voteId = _lido.adoptVote("Launch DG vote", EvmScriptUtils.encodeEvmCallScript(aragonVoteCalls)); + _lido.executeVote(voteId); + + assertEq(_getLastProposalId(), 2); + } + + _step("8. Schedule and execute the DG activation proposal"); + { + _wait(_getAfterSubmitDelay()); + _scheduleProposal(_getLastProposalId()); + _wait(_getAfterScheduleDelay()); + _executeProposal(_getLastProposalId()); + } + + _step("9. Verify that Voting has no permission to forward to Agent"); + { + ExternalCall[] memory someAgentForwardCall; + someAgentForwardCall = ExternalCallHelpers.create( + [ + ExternalCall({ + target: address(_lido.acl), + value: 0, + payload: abi.encodeWithSelector( + _lido.acl.revokePermission.selector, + _getAdminExecutor(), + (address(_lido.agent)), + _lido.agent.RUN_SCRIPT_ROLE() + ) + }) + ] + ); + + vm.expectRevert("AGENT_CAN_NOT_FORWARD"); + _lido.agent.forward(_encodeExternalCalls(someAgentForwardCall)); + } + } + + function testFork_DualGovernanceLaunchFromAragonVote() external { + _step("0. Deploy DG contracts"); + { + _deployDGSetup({isEmergencyProtectionEnabled: true}); + } + + _step("1. Validate The DG Initial State After Deployment"); + { + DeployVerification.verify(_deployArtifact); + } + + _step("2. Activate Emergency Mode"); + { + _activateEmergencyMode(); + } + + _step("3. Make Emergency Reset"); + { + _emergencyReset(); + } + + _step("4. Prepare Aragon Vote With Roles Transfer & DG Configuration"); + { + ExternalCall[] memory dgConfigurationProposalCalls = ExternalCallHelpers.create( + address(_timelock), + [ + abi.encodeCall( + _timelock.setEmergencyProtectionActivationCommittee, (_DEFAULT_EMERGENCY_ACTIVATION_COMMITTEE) + ), + abi.encodeCall( + _timelock.setEmergencyProtectionExecutionCommittee, (_DEFAULT_EMERGENCY_EXECUTION_COMMITTEE) + ), + abi.encodeCall(_timelock.setGovernance, (address(_dgDeployedContracts.dualGovernance))), + abi.encodeCall( + _timelock.setEmergencyProtectionEndDate, + (_DEFAULT_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now())) + ), + abi.encodeCall(_timelock.setEmergencyModeDuration, (_DEFAULT_EMERGENCY_MODE_DURATION)) + ] + ); + + EvmScriptUtils.EvmScriptCall[] memory aragonVoteCalls = new EvmScriptUtils.EvmScriptCall[](5); + + // Grant RUN_SCRIPT_ROLE to AdminExecutor + aragonVoteCalls[0].target = address(_lido.acl); + aragonVoteCalls[0].data = abi.encodeCall( + _lido.acl.grantPermission, + (address(_getAdminExecutor()), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + // Grant EXECUTE_ROLE to AdminExecutor + aragonVoteCalls[1].target = address(_lido.acl); + aragonVoteCalls[1].data = abi.encodeCall( + _lido.acl.grantPermission, + (address(_getAdminExecutor()), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + + // Transfer RUN_SCRIPT_ROLE manager to Agent + aragonVoteCalls[2].target = address(_lido.acl); + aragonVoteCalls[2].data = abi.encodeCall( + _lido.acl.setPermissionManager, + (address(_lido.agent), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + // Transfer EXECUTE_ROLE manager to Agent + aragonVoteCalls[3].target = address(_lido.acl); + aragonVoteCalls[3].data = abi.encodeCall( + _lido.acl.setPermissionManager, (address(_lido.agent), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + + // Submit proposal to EmergencyProtectedTimelock + aragonVoteCalls[4].target = address(_dgDeployedContracts.emergencyGovernance); + aragonVoteCalls[4].data = abi.encodeCall( + _dgDeployedContracts.emergencyGovernance.submitProposal, + (dgConfigurationProposalCalls, "Dual Governance Configuration") + ); + + bytes memory script = EvmScriptUtils.encodeEvmCallScript(aragonVoteCalls); + + uint256 readyToExecuteAragonVoteId = _lido.adoptVote("Dual Governance Launch", script); + + _lido.executeVote(readyToExecuteAragonVoteId); + } + + _step("5. Wait & Execute Timelock Proposal"); + { + assertEq( + _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), + address(_lido.agent) + ); + + assertTrue(_lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE())); + assertTrue( + _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + assertTrue( + _lido.acl.hasPermission(address(_getAdminExecutor()), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + assertTrue( + _lido.acl.hasPermission( + address(_getAdminExecutor()), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE() + ) + ); + + uint256 launchProposalId = 1; + assertEq(_timelock.getProposalsCount(), 1); + + _wait(_getAfterSubmitDelay()); + _scheduleProposal(launchProposalId); + + _wait(_getAfterScheduleDelay()); + _executeProposal(launchProposalId); + } + + _step("6. Validate The State Before Final Step Of DG Launch"); + { + assertTrue(_lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE())); + assertTrue( + _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + assertTrue( + _lido.acl.hasPermission(address(_getAdminExecutor()), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + assertTrue( + _lido.acl.hasPermission( + address(_getAdminExecutor()), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE() + ) + ); + + assertEq( + _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.EXECUTE_ROLE()), address(_lido.agent) + ); + + assertEq( + _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), + address(_lido.agent) + ); + } + + _step("7. Submit Dual Governance To Revoke Agent Forwarding From Voting"); + { + ExternalCall[] memory votingRevokePermissionsCalls = ExternalCallHelpers.create( + [ + ExternalCall({ + value: 0, + target: address(_lido.agent), + payload: abi.encodeCall( + _lido.agent.forward, + EvmScriptUtils.encodeEvmCallScript( + address(_lido.acl), + abi.encodeCall( + _lido.acl.revokePermission, + (address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ) + ) + ) + }), + ExternalCall({ + value: 0, + target: address(_lido.agent), + payload: abi.encodeCall( + _lido.agent.forward, + EvmScriptUtils.encodeEvmCallScript( + address(_lido.acl), + abi.encodeCall( + _lido.acl.revokePermission, + (address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ) + ) + ) + }) + ] + ); + + uint256 dgLaunchPoposalId = + _submitProposalByAdminProposer(votingRevokePermissionsCalls, "DG Launch Final Step"); + assertEq(_timelock.getProposalsCount(), 2); + + _wait(_getAfterSubmitDelay()); + _scheduleProposal(dgLaunchPoposalId); + + _wait(_getAfterScheduleDelay()); + _executeProposal(dgLaunchPoposalId); + } + + _step("8. Validate The Voting Has No Permission to Forward to Agent"); + { + assertFalse( + _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + assertFalse( + _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) + ); + + assertTrue( + _lido.acl.hasPermission(address(_getAdminExecutor()), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) + ); + assertTrue( + _lido.acl.hasPermission( + address(_getAdminExecutor()), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE() + ) + ); + + assertEq( + _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.EXECUTE_ROLE()), address(_lido.agent) + ); + + assertEq( + _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), + address(_lido.agent) + ); + } + } + + function _encodeExternalCalls(ExternalCall[] memory calls) internal pure returns (bytes memory result) { + result = abi.encodePacked(bytes4(uint32(1))); + + for (uint256 i = 0; i < calls.length; ++i) { + ExternalCall memory call = calls[i]; + result = abi.encodePacked(result, bytes20(call.target), bytes4(uint32(call.payload.length)), call.payload); + } + } +} + +contract MockRolesVerifier { + event AllRolesVerified(); + + function validate(address dgAdminExecutor, address dgResealManager) external { + emit AllRolesVerified(); + } +} + +contract MockDGStateVerifier { + event DGStateVerified(); + + function validate(address dualGovernance, address timelock) external { + emit DGStateVerified(); + } +} diff --git a/test/scenario/dg-launch.t.sol b/test/scenario/dg-launch.t.sol deleted file mode 100644 index ae5ebea5..00000000 --- a/test/scenario/dg-launch.t.sol +++ /dev/null @@ -1,248 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {Timestamps} from "contracts/types/Timestamp.sol"; - -import {LidoUtils} from "test/utils/lido-utils.sol"; -import {EvmScriptUtils} from "test/utils/evm-script-utils.sol"; - -import {ExternalCall, ExternalCallHelpers, ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; - -contract DGLaunchTest is ScenarioTestBlueprint { - using LidoUtils for LidoUtils.Context; - - function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); - } - - function testFork_DualGovernanceLaunchFromAragonVote() external { - _step("0. Validate The DG Initial State After Deployment"); - // TODO: call DeployVerification lib - assertNotEq(address(_emergencyGovernance), address(0)); - assertEq(_timelock.getEmergencyGovernance(), address(_emergencyGovernance)); - - _step("1. Activate Emergency Mode"); - { - assertFalse(_timelock.isEmergencyModeActive()); - - vm.prank(_emergencyActivationCommittee); - _timelock.activateEmergencyMode(); - - assertTrue(_timelock.isEmergencyModeActive()); - } - - _step("2. Make Emergency Reset"); - { - assertEq(_timelock.getGovernance(), address(_dualGovernance)); - - vm.prank(_emergencyExecutionCommittee); - _timelock.emergencyReset(); - - assertEq(_timelock.getGovernance(), address(_emergencyGovernance)); - } - - _step("3. Prepare Aragon Vote With Roles Transfer & DG Configuration"); - { - ExternalCall[] memory dgConfigurationProposalCalls = ExternalCallHelpers.create( - [ - ExternalCall({ - value: 0, - target: address(_timelock), - payload: abi.encodeCall( - _timelock.setEmergencyProtectionActivationCommittee, (_emergencyActivationCommittee) - ) - }), - ExternalCall({ - value: 0, - target: address(_timelock), - payload: abi.encodeCall( - _timelock.setEmergencyProtectionExecutionCommittee, (_emergencyExecutionCommittee) - ) - }), - ExternalCall({ - value: 0, - target: address(_timelock), - payload: abi.encodeCall(_timelock.setGovernance, (address(_dualGovernance))) - }), - ExternalCall({ - value: 0, - target: address(_timelock), - payload: abi.encodeCall( - _timelock.setEmergencyProtectionEndDate, _dgDeployConfig.EMERGENCY_PROTECTION_END_DATE - ) - }), - ExternalCall({ - value: 0, - target: address(_timelock), - payload: abi.encodeCall(_timelock.setEmergencyModeDuration, (_dgDeployConfig.EMERGENCY_MODE_DURATION)) - }) - ] - ); - - EvmScriptUtils.EvmScriptCall[] memory aragonVoteCalls = new EvmScriptUtils.EvmScriptCall[](5); - - // Grant RUN_SCRIPT_ROLE to AdminExecutor - aragonVoteCalls[0].target = address(_lido.acl); - aragonVoteCalls[0].data = abi.encodeCall( - _lido.acl.grantPermission, - (address(_adminExecutor), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - // Grant EXECUTE_ROLE to AdminExecutor - aragonVoteCalls[1].target = address(_lido.acl); - aragonVoteCalls[1].data = abi.encodeCall( - _lido.acl.grantPermission, (address(_adminExecutor), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - - // Transfer RUN_SCRIPT_ROLE manager to Agent - aragonVoteCalls[2].target = address(_lido.acl); - aragonVoteCalls[2].data = abi.encodeCall( - _lido.acl.setPermissionManager, - (address(_lido.agent), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - // Transfer EXECUTE_ROLE manager to Agent - aragonVoteCalls[3].target = address(_lido.acl); - aragonVoteCalls[3].data = abi.encodeCall( - _lido.acl.setPermissionManager, (address(_lido.agent), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - - // Submit proposal to EmergencyProtectedTimelock - aragonVoteCalls[4].target = address(_emergencyGovernance); - aragonVoteCalls[4].data = abi.encodeCall( - _emergencyGovernance.submitProposal, (dgConfigurationProposalCalls, "Dual Governance Configuration") - ); - - bytes memory script = EvmScriptUtils.encodeEvmCallScript(aragonVoteCalls); - - uint256 readyToExecuteAragonVoteId = _lido.adoptVote("Dual Governance Launch", script); - - _lido.executeVote(readyToExecuteAragonVoteId); - } - - _step("4. Wait & Execute Timelock Proposal"); - { - assertEq( - _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), - address(_lido.agent) - ); - - assertTrue(_lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE())); - assertTrue( - _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - uint256 launchProposalId = 1; - assertEq(_timelock.getProposalsCount(), 1); - - _waitAfterSubmitDelayPassed(); - _scheduleProposal(_emergencyGovernance, launchProposalId); - - _waitAfterScheduleDelayPassed(); - _executeProposal(launchProposalId); - } - - _step("5. Validate The State Before Final Step Of DG Launch"); - { - assertTrue(_lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE())); - assertTrue( - _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - assertEq( - _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.EXECUTE_ROLE()), address(_lido.agent) - ); - - assertEq( - _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), - address(_lido.agent) - ); - } - - _step("6. Submit Dual Governance To Revoke Agent Forwarding From Voting"); - { - ExternalCall[] memory votingRevokePermissionsCalls = ExternalCallHelpers.create( - [ - ExternalCall({ - value: 0, - target: address(_lido.agent), - payload: abi.encodeCall( - _lido.agent.forward, - EvmScriptUtils.encodeEvmCallScript( - address(_lido.acl), - abi.encodeCall( - _lido.acl.revokePermission, - (address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ) - ) - ) - }), - ExternalCall({ - value: 0, - target: address(_lido.agent), - payload: abi.encodeCall( - _lido.agent.forward, - EvmScriptUtils.encodeEvmCallScript( - address(_lido.acl), - abi.encodeCall( - _lido.acl.revokePermission, - (address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ) - ) - ) - }) - ] - ); - - uint256 dgLaunchPoposalId = - _submitProposal(_dualGovernance, "DG Launch Final Step", votingRevokePermissionsCalls); - assertEq(_timelock.getProposalsCount(), 2); - - _waitAfterSubmitDelayPassed(); - _scheduleProposalViaDualGovernance(dgLaunchPoposalId); - - _waitAfterScheduleDelayPassed(); - _executeProposal(dgLaunchPoposalId); - } - - _step("7. Validate The Voting Has No Permission to Forward to Agent"); - { - assertFalse( - _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - assertFalse( - _lido.acl.hasPermission(address(_lido.voting), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.EXECUTE_ROLE()) - ); - assertTrue( - _lido.acl.hasPermission(address(_adminExecutor), address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()) - ); - - assertEq( - _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.EXECUTE_ROLE()), address(_lido.agent) - ); - - assertEq( - _lido.acl.getPermissionManager(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE()), - address(_lido.agent) - ); - } - } -} diff --git a/test/scenario/dg-update-tokens-rotation.t.sol b/test/scenario/dg-update-tokens-rotation.t.sol index 7a59727b..170b658c 100644 --- a/test/scenario/dg-update-tokens-rotation.t.sol +++ b/test/scenario/dg-update-tokens-rotation.t.sol @@ -10,13 +10,22 @@ import {ExecutableProposals, Status as ProposalStatus} from "contracts/libraries import {Escrow} from "contracts/Escrow.sol"; import {DualGovernance} from "contracts/DualGovernance.sol"; -import {ScenarioTestBlueprint, ExternalCall, ExternalCallHelpers} from "../utils/scenario-test-blueprint.sol"; - -contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { +import { + LidoUtils, + IRageQuitEscrow, + ContractsDeployment, + DGScenarioTestSetup, + ExternalCallHelpers, + ExternalCall, + Proposers, + IGovernance +} from "../utils/integration-tests.sol"; + +contract DualGovernanceUpdateTokensRotation is DGScenarioTestSetup { address internal immutable _VETOER = makeAddr("VETOER"); function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _deployDGSetup({isEmergencyProtectionEnabled: false}); _setupStETHBalance(_VETOER, PercentsD16.fromBasisPoints(30_00)); } @@ -24,31 +33,35 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { DualGovernance newDualGovernanceInstance; _step("1. Deploy new Dual Governance implementation"); { - newDualGovernanceInstance = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider - }); + newDualGovernanceInstance = ContractsDeployment.deployDualGovernance( + DualGovernance.DualGovernanceComponents({ + timelock: _timelock, + resealManager: _dgDeployedContracts.resealManager, + configProvider: _dgDeployedContracts.dualGovernanceConfigProvider + }), + _dgDeployConfig.dualGovernance.signallingTokens, + _dgDeployConfig.dualGovernance.sanityCheckParams + ); } uint256 updateDualGovernanceProposalId; _step("2. Submit proposal to update the Dual Governance implementation"); { - updateDualGovernanceProposalId = _submitProposalViaDualGovernance( - "Update the Dual Governance implementation", - _getActionsToUpdateDualGovernanceImplementation(address(newDualGovernanceInstance)) + updateDualGovernanceProposalId = _submitProposalByAdminProposer( + _getActionsToUpdateDualGovernanceImplementation(address(newDualGovernanceInstance)), + "Update the Dual Governance implementation" ); } _step("3. Users accumulate some stETH in the Signalling Escrow"); { - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() - PercentsD16.from(1)); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport() - PercentsD16.from(1)); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _assertVetoSignallingDeactivationState(); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); @@ -56,10 +69,10 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { _step("4. When the VetoCooldown is entered proposal to update becomes executable"); { - _scheduleProposalViaDualGovernance(updateDualGovernanceProposalId); + _scheduleProposal(updateDualGovernanceProposalId); _assertProposalScheduled(updateDualGovernanceProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(updateDualGovernanceProposalId); assertEq(_timelock.getGovernance(), address(newDualGovernanceInstance)); @@ -68,16 +81,18 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { _step("5. The old instance of the Dual Governance can't submit proposals anymore"); { // wait until the VetoCooldown ends in the old dual governance instance - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertVetoSignalingState(); // old instance of the Dual Governance can't submit proposals anymore vm.expectRevert( - abi.encodeWithSelector(TimelockState.CallerIsNotGovernance.selector, address(_dualGovernance)) + abi.encodeWithSelector( + TimelockState.CallerIsNotGovernance.selector, address(_dgDeployedContracts.dualGovernance) + ) ); vm.prank(address(_lido.voting)); - _dualGovernance.submitProposal(_getMockTargetRegularStaffCalls(), "empty metadata"); + _dgDeployedContracts.dualGovernance.submitProposal(_getMockTargetRegularStaffCalls(), "Regular actions"); } _step("6. Users can unlock stETH from the old Signalling Escrow"); @@ -88,13 +103,13 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { _step("7. Users can withdraw funds even if the Rage Quit is started in the old instance of the Dual Governance"); { // the Rage Quit started on the old DualGovernance instance - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport()); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); _assertRageQuitState(); // The Rage Quit may be finished in the previous DG instance so vetoers will not lose their funds by mistake - Escrow rageQuitEscrow = Escrow(payable(_dualGovernance.getRageQuitEscrow())); + IRageQuitEscrow rageQuitEscrow = _getRageQuitEscrow(); while (!rageQuitEscrow.isWithdrawalsBatchesClosed()) { rageQuitEscrow.requestNextWithdrawalsBatch(96); @@ -108,11 +123,11 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { rageQuitEscrow.startRageQuitExtensionPeriod(); - _wait(_dualGovernanceConfigProvider.RAGE_QUIT_EXTENSION_PERIOD_DURATION().plusSeconds(1)); + _wait(_getRageQuitExtensionPeriodDuration().plusSeconds(1)); assertEq(rageQuitEscrow.isRageQuitFinalized(), true); // TODO: Add method Escrow.getRageQuitExtensionPeriodDuration() - _wait(_dualGovernanceConfigProvider.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY()); + _wait(_getRageQuitEthWithdrawalsDelay()); uint256 vetoerETHBalanceBefore = _VETOER.balance; @@ -132,46 +147,50 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { DualGovernance newDualGovernanceInstance; _step("1. Deploy new Dual Governance implementation"); { - newDualGovernanceInstance = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider - }); + newDualGovernanceInstance = ContractsDeployment.deployDualGovernance( + DualGovernance.DualGovernanceComponents({ + timelock: _timelock, + resealManager: _dgDeployedContracts.resealManager, + configProvider: _dgDeployedContracts.dualGovernanceConfigProvider + }), + _dgDeployConfig.dualGovernance.signallingTokens, + _dgDeployConfig.dualGovernance.sanityCheckParams + ); } uint256 updateDualGovernanceProposalId; _step("2. DAO submits proposal to update the Dual Governance implementation"); { - updateDualGovernanceProposalId = _submitProposalViaDualGovernance( - "Update the Dual Governance implementation", - _getActionsToUpdateDualGovernanceImplementation(address(newDualGovernanceInstance)) + updateDualGovernanceProposalId = _submitProposalByAdminProposer( + _getActionsToUpdateDualGovernanceImplementation(address(newDualGovernanceInstance)), + "Update the Dual Governance implementation" ); } _step("3. Malicious actor accumulate second seal in the Signalling Escrow"); { - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().minusSeconds(_lido.voting.voteTime())); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport()); + _wait(_getVetoSignallingMaxDuration().minusSeconds(_lido.voting.voteTime())); _assertVetoSignalingState(); } uint256 maliciousProposalId; _step("4. Malicious actor unlock funds from Signalling Escrow"); { - maliciousProposalId = _submitProposalViaDualGovernance( - "Steal control over timelock contract", + maliciousProposalId = _submitProposalByAdminProposer( ExternalCallHelpers.create({ target: address(_timelock), payload: abi.encodeCall(_timelock.setGovernance, (_VETOER)) - }) + }), + "Steal control over timelock contract" ); _unlockStETH(_VETOER); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); } _step("5. Regular can't collect second seal in VETO_SIGNALLING_DEACTIVATION_MAX_DURATION"); { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); } @@ -183,12 +202,12 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { vm.expectRevert( abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, maliciousProposalId) ); - _scheduleProposalViaDualGovernance(maliciousProposalId); + _dgDeployedContracts.dualGovernance.scheduleProposal(maliciousProposalId); - _scheduleProposalViaDualGovernance(updateDualGovernanceProposalId); + _scheduleProposal(updateDualGovernanceProposalId); _assertProposalScheduled(updateDualGovernanceProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(updateDualGovernanceProposalId); assertEq(_timelock.getGovernance(), address(newDualGovernanceInstance)); @@ -233,4 +252,11 @@ contract DualGovernanceUpdateTokensRotation is ScenarioTestBlueprint { ] ); } + + function external__submitProposalByAdminProposer(ExternalCall[] memory calls) + external + returns (uint256 proposalId) + { + _submitProposalByAdminProposer(calls); + } } diff --git a/test/scenario/escrow.t.sol b/test/scenario/escrow.t.sol index 8470f52c..96a39421 100644 --- a/test/scenario/escrow.t.sol +++ b/test/scenario/escrow.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.26; import {console} from "forge-std/Test.sol"; +import {Timestamps} from "contracts/types/Timestamp.sol"; import {Duration, Durations} from "contracts/types/Duration.sol"; import {PercentsD16} from "contracts/types/PercentD16.sol"; @@ -15,9 +16,15 @@ import {AssetsAccounting, UnstETHRecordStatus} from "contracts/libraries/AssetsA import {Escrow} from "contracts/Escrow.sol"; -import {ScenarioTestBlueprint, LidoUtils, console} from "../utils/scenario-test-blueprint.sol"; +import { + LidoUtils, + ContractsDeployment, + DGScenarioTestSetup, + ExternalCallHelpers, + ExternalCall +} from "../utils/integration-tests.sol"; -contract EscrowHappyPath is ScenarioTestBlueprint { +contract EscrowHappyPath is DGScenarioTestSetup { using LidoUtils for LidoUtils.Context; Escrow internal escrow; @@ -29,9 +36,9 @@ contract EscrowHappyPath is ScenarioTestBlueprint { address internal immutable _VETOER_2 = makeAddr("VETOER_2"); function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _deployDGSetup({isEmergencyProtectionEnabled: false}); - escrow = _getVetoSignallingEscrow(); + escrow = Escrow(payable(address(_getVetoSignallingEscrow()))); _setupStETHBalance(_VETOER_1, PercentsD16.fromBasisPoints(10_00)); @@ -72,7 +79,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _lockStETH(_VETOER_2, secondVetoerLockStETHAmount); _lockWstETH(_VETOER_2, secondVetoerLockWstETHAmount); - _wait(_dualGovernanceConfigProvider.MIN_ASSETS_LOCK_DURATION().plusSeconds(1)); + _wait(_getMinAssetsLockDuration().plusSeconds(1)); _unlockStETH(_VETOER_1); assertApproxEqAbs( @@ -108,7 +115,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _simulateRebase(PercentsD16.fromBasisPoints(101_00)); // +1% - _wait(_dualGovernanceConfigProvider.MIN_ASSETS_LOCK_DURATION().plusSeconds(1)); + _wait(_getMinAssetsLockDuration().plusSeconds(1)); _unlockWstETH(_VETOER_1); assertApproxEqAbs( @@ -150,7 +157,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _simulateRebase(PercentsD16.fromBasisPoints(99_00)); // -1% - _wait(_dualGovernanceConfigProvider.MIN_ASSETS_LOCK_DURATION().plusSeconds(1)); + _wait(_getMinAssetsLockDuration().plusSeconds(1)); _unlockStETH(_VETOER_1); assertApproxEqAbs( @@ -183,7 +190,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _lockUnstETH(_VETOER_1, unstETHIds); - _wait(_dualGovernanceConfigProvider.MIN_ASSETS_LOCK_DURATION().plusSeconds(1)); + _wait(_getMinAssetsLockDuration().plusSeconds(1)); _unlockUnstETH(_VETOER_1, unstETHIds); } @@ -305,7 +312,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { vm.expectRevert(); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); - vm.prank(address(_dualGovernance)); + vm.prank(address(_dgDeployedContracts.dualGovernance)); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); uint256 escrowStETHBalance = _lido.stETH.balanceOf(address(escrow)); @@ -389,7 +396,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _lockUnstETH(_VETOER_1, unstETHIds); - vm.prank(address(_dualGovernance)); + vm.prank(address(_dgDeployedContracts.dualGovernance)); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); _finalizeWithdrawalQueue(); @@ -433,7 +440,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _lockUnstETH(_VETOER_1, unstETHIds); - vm.prank(address(_dualGovernance)); + vm.prank(address(_dgDeployedContracts.dualGovernance)); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); vm.expectRevert(Escrow.BatchesQueueIsNotClosed.selector); @@ -481,7 +488,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _lockWstETH(_VETOER_1, 1 ether); _lockUnstETH(_VETOER_1, lockedWithdrawalNfts); - vm.prank(address(_dualGovernance)); + vm.prank(address(_dgDeployedContracts.dualGovernance)); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); // --- @@ -515,18 +522,16 @@ contract EscrowHappyPath is ScenarioTestBlueprint { _assertVetoSignalingState(); // wait till the last second of the dynamic timelock duration - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION()); + _wait(_getVetoSignallingMaxDuration()); _activateNextState(); _assertVetoSignalingState(); - ( /* bool isActive */ , uint256 duration, uint256 activatedAt, /* uint256 enteredAt */ ) = - _getVetoSignallingState(); - assertEq(duration + activatedAt, block.timestamp); + assertEq(_getVetoSignallingDuration().addTo(_getVetoSignallingActivatedAt()), Timestamps.now()); // validate that while the VetoSignalling has not passed, vetoer can unlock funds from Escrow uint256 snapshotId = vm.snapshot(); _unlockStETH(_VETOER_1); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); // Rollback the state of the node before vetoer unlocked his funds vm.revertTo(snapshotId); @@ -567,7 +572,7 @@ contract EscrowHappyPath is ScenarioTestBlueprint { // Lock stETH to generate batch _lockStETH(_VETOER_1, 20 * requestAmount); - vm.prank(address(_dualGovernance)); + vm.prank(address(_dgDeployedContracts.dualGovernance)); escrow.startRageQuit(_RAGE_QUIT_EXTRA_TIMELOCK, _RAGE_QUIT_WITHDRAWALS_TIMELOCK); uint256 batchSizeLimit = 16; diff --git a/test/scenario/executor-ownership-transfer.t.sol b/test/scenario/executor-ownership-transfer.t.sol index 48e68c7c..9b30e2bd 100644 --- a/test/scenario/executor-ownership-transfer.t.sol +++ b/test/scenario/executor-ownership-transfer.t.sol @@ -6,46 +6,47 @@ import {Durations} from "contracts/types/Duration.sol"; import {Ownable, Executor} from "contracts/Executor.sol"; import {Proposers} from "contracts/libraries/Proposers.sol"; -import {ExternalCall, ScenarioTestBlueprint, ExternalCallHelpers} from "../utils/scenario-test-blueprint.sol"; +import {DGScenarioTestSetup, ExternalCallHelpers, ExternalCall, DualGovernance} from "../utils/integration-tests.sol"; interface ISomeContract { function someMethod(uint256 someParameter) external; } -contract ExecutorOwnershipTransfer is ScenarioTestBlueprint { +contract ExecutorOwnershipTransferScenarioTest is DGScenarioTestSetup { address private immutable _NEW_REGULAR_PROPOSER = makeAddr("NEW_REGULAR_PROPOSER"); Executor private _oldAdminExecutor; Executor private _newAdminExecutor; function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _deployDGSetup({isEmergencyProtectionEnabled: false}); _newAdminExecutor = new Executor({owner: address(this)}); - _oldAdminExecutor = Executor(payable(_timelock.getAdminExecutor())); + _oldAdminExecutor = Executor(payable(_getAdminExecutor())); _newAdminExecutor.transferOwnership(address(_timelock)); } function testFork_ExecutorOwnershipTransfer_HappyPath() external { - _step("1. DAO creates proposal to add new proposer and change the admin executor"); uint256 shuffleExecutorsProposalId; + DualGovernance dualGovernance = DualGovernance(_getGovernance()); + _step("1. DAO creates proposal to add new proposer and change the admin executor"); { ExternalCall[] memory executorsShuffleCalls = ExternalCallHelpers.create( [ // 1. Register new proposer and assign it to the old admin executor ExternalCall({ value: 0, - target: address(_dualGovernance), + target: address(dualGovernance), payload: abi.encodeCall( - _dualGovernance.registerProposer, (_NEW_REGULAR_PROPOSER, address(_oldAdminExecutor)) + dualGovernance.registerProposer, (_NEW_REGULAR_PROPOSER, address(_oldAdminExecutor)) ) }), // 2. Assign previous proposer (Aragon Voting) to the new executor ExternalCall({ value: 0, - target: address(_dualGovernance), + target: address(dualGovernance), payload: abi.encodeCall( - _dualGovernance.setProposerExecutor, (address(_lido.voting), address(_newAdminExecutor)) + dualGovernance.setProposerExecutor, (address(_lido.voting), address(_newAdminExecutor)) ) }), // 3. Replace the admin executor of the Timelock contract @@ -57,25 +58,25 @@ contract ExecutorOwnershipTransfer is ScenarioTestBlueprint { ] ); shuffleExecutorsProposalId = - _submitProposalViaDualGovernance("Register new proposer and swap executors", executorsShuffleCalls); + _submitProposalByAdminProposer(executorsShuffleCalls, "Register new proposer and swap executors"); } _step("2. Proposal is scheduled and executed"); { _assertProposalSubmitted(shuffleExecutorsProposalId); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _scheduleProposalViaDualGovernance(shuffleExecutorsProposalId); + _scheduleProposal(shuffleExecutorsProposalId); _assertProposalScheduled(shuffleExecutorsProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(shuffleExecutorsProposalId); } _step("3. The proposers and executors were set up correctly"); { - assertEq(_timelock.getAdminExecutor(), address(_newAdminExecutor)); + assertEq(_getAdminExecutor(), address(_newAdminExecutor)); - Proposers.Proposer[] memory proposers = _dualGovernance.getProposers(); + Proposers.Proposer[] memory proposers = _getProposers(); assertEq(proposers.length, 2); @@ -92,8 +93,8 @@ contract ExecutorOwnershipTransfer is ScenarioTestBlueprint { [ ExternalCall({ value: 0, - target: address(_dualGovernance), - payload: abi.encodeCall(_dualGovernance.unregisterProposer, (_NEW_REGULAR_PROPOSER)) + target: address(dualGovernance), + payload: abi.encodeCall(dualGovernance.unregisterProposer, (_NEW_REGULAR_PROPOSER)) }), ExternalCall({ value: 0, @@ -127,25 +128,24 @@ contract ExecutorOwnershipTransfer is ScenarioTestBlueprint { ] ); - uint256 proposalId = - _submitProposalViaDualGovernance("Manage Dual Governance parameters", dgManageOperations); + uint256 proposalId = _submitProposalByAdminProposer(dgManageOperations, "Manage Dual Governance parameters"); _assertProposalSubmitted(proposalId); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _scheduleProposalViaDualGovernance(proposalId); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(proposalId); - Proposers.Proposer[] memory proposers = _dualGovernance.getProposers(); + Proposers.Proposer[] memory proposers = _getProposers(); assertEq(proposers.length, 1); assertEq(proposers[0].account, address(_lido.voting)); assertEq(proposers[0].executor, address(_newAdminExecutor)); - assertEq(_timelock.getAfterScheduleDelay(), Durations.ZERO); + assertEq(_getAfterScheduleDelay(), Durations.ZERO); assertEq(_oldAdminExecutor.owner(), address(_timelock)); } diff --git a/test/scenario/gov-state-transitions.t.sol b/test/scenario/gov-state-transitions.t.sol index a5eafee8..ab99c90f 100644 --- a/test/scenario/gov-state-transitions.t.sol +++ b/test/scenario/gov-state-transitions.t.sol @@ -3,51 +3,51 @@ pragma solidity 0.8.26; import {Durations} from "contracts/types/Duration.sol"; import {PercentsD16} from "contracts/types/PercentD16.sol"; -import {ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; +// import {ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; -contract GovernanceStateTransitions is ScenarioTestBlueprint { +import {DGScenarioTestSetup, ExternalCallHelpers, ExternalCall, DualGovernance} from "../utils/integration-tests.sol"; + +contract GovernanceStateTransitions is DGScenarioTestSetup { address internal immutable _VETOER = makeAddr("VETOER"); function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); - _setupStETHBalance( - _VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); + _deployDGSetup({isEmergencyProtectionEnabled: false}); + _setupStETHBalance(_VETOER, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); } - function test_signalling_state_min_duration() public { + function testFork_VetoSignallingStateMinDuration() external { _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() - PercentsD16.from(1)); + _lockStETH(_VETOER, _getFirstSealRageQuitSupport() - PercentsD16.from(1)); _assertNormalState(); _lockStETH(_VETOER, 1 gwei); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION().dividedBy(2)); + _wait(_getVetoSignallingMinDuration().dividedBy(2)); _activateNextState(); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION().dividedBy(2).plusSeconds(1)); + _wait(_getVetoSignallingMinDuration().dividedBy(2).plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); } - function test_signalling_state_max_duration() public { + function testFork_VetoSignallingStateMaxDuration() public { _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport()); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().dividedBy(2)); + _wait(_getVetoSignallingMaxDuration().dividedBy(2)); _activateNextState(); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().dividedBy(2)); + _wait(_getVetoSignallingMaxDuration().dividedBy(2)); _activateNextState(); _assertVetoSignalingState(); @@ -60,22 +60,22 @@ contract GovernanceStateTransitions is ScenarioTestBlueprint { _assertRageQuitState(); } - function test_signalling_to_normal() public { + function testFork_VetoSignallingToNormal() public { _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() - PercentsD16.from(1)); + _lockStETH(_VETOER, _getFirstSealRageQuitSupport() - PercentsD16.from(1)); _assertNormalState(); _lockStETH(_VETOER, 1 gwei); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); @@ -84,44 +84,44 @@ contract GovernanceStateTransitions is ScenarioTestBlueprint { _getVetoSignallingEscrow().unlockStETH(); vm.stopPrank(); - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertNormalState(); } - function test_signalling_non_stop() public { + function testFork_VetoSignallingVetoCooldownCycle() public { _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() - PercentsD16.from(1)); + _lockStETH(_VETOER, _getFirstSealRageQuitSupport() - PercentsD16.from(1)); _assertNormalState(); _lockStETH(_VETOER, 1 gwei); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertVetoSignalingState(); } - function test_signalling_to_rage_quit() public { + function testFork_VetoSignallingToRageQuit() public { _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); + _lockStETH(_VETOER, _getSecondSealRageQuitSupport()); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION()); + _wait(_getVetoSignallingMaxDuration()); _activateNextState(); _assertVetoSignalingState(); diff --git a/test/scenario/happy-path-plan-b.t.sol b/test/scenario/happy-path-plan-b.t.sol index b387c9c6..2fbd09d7 100644 --- a/test/scenario/happy-path-plan-b.t.sol +++ b/test/scenario/happy-path-plan-b.t.sol @@ -1,98 +1,92 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; -import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; +import {PercentsD16} from "contracts/types/PercentD16.sol"; -import { - ScenarioTestBlueprint, - ExternalCall, - ExternalCallHelpers, - Timestamp, - Timestamps, - Durations -} from "../utils/scenario-test-blueprint.sol"; - -import {DualGovernance} from "contracts/DualGovernance.sol"; import {EmergencyProtection} from "contracts/libraries/EmergencyProtection.sol"; import {ExecutableProposals, Status as ProposalStatus} from "contracts/libraries/ExecutableProposals.sol"; -contract PlanBSetup is ScenarioTestBlueprint { +import {ResealManager} from "contracts/ResealManager.sol"; +import {DualGovernance} from "contracts/DualGovernance.sol"; +import {ImmutableDualGovernanceConfigProvider} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; + +import { + Durations, + Timestamps, + ContractsDeployment, + IPotentiallyDangerousContract, + TGScenarioTestSetup, + DGScenarioTestSetup, + ExternalCall, + ExternalCallHelpers +} from "../utils/integration-tests.sol"; + +contract PlanBSetup is TGScenarioTestSetup, DGScenarioTestSetup { function setUp() external { - _deployTimelockedGovernanceSetup({isEmergencyProtectionEnabled: true}); + _deployTGSetup({isEmergencyProtectionEnabled: true}); } - function testFork_PlanB_Scenario() external { + function testFork_TimelockedGovernanceMigrationToDualGovernance() external { ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); // --- // ACT 1. 📈 DAO OPERATES AS USUALLY // --- { - uint256 proposalId = _submitProposal( - _timelockedGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls - ); + uint256 proposalId = + _submitProposal(regularStaffCalls, "DAO does regular staff on potentially dangerous contract"); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _assertCanScheduleViaTimelockedGovernance(proposalId, false); + _assertCanSchedule(proposalId, false); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaTimelockedGovernance(proposalId, true); - _scheduleProposalViaTimelockedGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); _executeProposal(proposalId); - _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); } // --- // ACT 2. 😱 DAO IS UNDER ATTACK // --- uint256 maliciousProposalId; - IEmergencyProtectedTimelock.EmergencyProtectionDetails memory emergencyState; { // Malicious vote was proposed by the attacker with huge LDO wad (but still not the majority) ExternalCall[] memory maliciousCalls = ExternalCallHelpers.create( address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doRugPool, ()) ); - maliciousProposalId = _submitProposalViaTimelockedGovernance("Rug Pool attempt", maliciousCalls); + maliciousProposalId = _submitProposal(maliciousCalls, "Rug Pool attempt"); // the call isn't executable until the delay has passed _assertProposalSubmitted(maliciousProposalId); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, false); + _assertCanSchedule(maliciousProposalId, false); // some time required to assemble the emergency committee and activate emergency mode - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); + _wait(_getAfterSubmitDelay().dividedBy(2)); // malicious call still can't be scheduled - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, false); + _assertCanSchedule(maliciousProposalId, false); // emergency committee activates emergency mode - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - // emergency mode was successfully activated - Timestamp expectedEmergencyModeEndTimestamp = _EMERGENCY_MODE_DURATION.addTo(Timestamps.now()); - emergencyState = _timelock.getEmergencyProtectionDetails(); - - assertTrue(_timelock.isEmergencyModeActive()); - assertEq(emergencyState.emergencyModeEndsAfter, expectedEmergencyModeEndTimestamp); + _activateEmergencyMode(); // after the submit delay has passed, the call still may be scheduled, but executed // only the emergency committee - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, true); - _scheduleProposalViaTimelockedGovernance(maliciousProposalId); + _assertCanSchedule(maliciousProposalId, true); + _scheduleProposal(maliciousProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); // but the call still not executable _assertCanExecute(maliciousProposalId, false); @@ -107,23 +101,31 @@ contract PlanBSetup is ScenarioTestBlueprint { { // Lido contributors work hard to implement and ship the Dual Governance mechanism // before the emergency mode is over - _wait(_EMERGENCY_PROTECTION_DURATION.dividedBy(2)); + _wait(_getEmergencyModeDuration().dividedBy(2)); // Time passes but malicious proposal still on hold _assertCanExecute(maliciousProposalId, false); // Dual Governance is deployed into mainnet - _resealManager = _deployResealManager(_timelock); - _dualGovernanceConfigProvider = _deployDualGovernanceConfigProvider(); - _dualGovernance = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider + _setDGDeployConfig(_getDefaultDGDeployConfig({emergencyGovernanceProposer: address(_lido.voting)})); + + _dgDeployedContracts.resealManager = ContractsDeployment.deployResealManager(_timelock); + _dgDeployedContracts.dualGovernanceConfigProvider = + ContractsDeployment.deployDualGovernanceConfigProvider(_dgDeployConfig.dualGovernanceConfigProvider); + + _dgDeployedContracts.dualGovernance = ContractsDeployment.deployDualGovernance({ + components: DualGovernance.DualGovernanceComponents({ + timelock: _timelock, + resealManager: _dgDeployedContracts.resealManager, + configProvider: _dgDeployedContracts.dualGovernanceConfigProvider + }), + signallingTokens: _dgDeployConfig.dualGovernance.signallingTokens, + sanityCheckParams: _dgDeployConfig.dualGovernance.sanityCheckParams }); ExternalCall[] memory dualGovernanceLaunchCalls = ExternalCallHelpers.create( [ - address(_dualGovernance), + address(_dgDeployedContracts.dualGovernance), address(_timelock), address(_timelock), address(_timelock), @@ -132,42 +134,48 @@ contract PlanBSetup is ScenarioTestBlueprint { address(_timelock) ], [ - abi.encodeCall(_dualGovernance.registerProposer, (address(_lido.voting), _timelock.getAdminExecutor())), + abi.encodeCall( + _dgDeployedContracts.dualGovernance.registerProposer, + (address(_lido.voting), _timelock.getAdminExecutor()) + ), // Only Dual Governance contract can call the Timelock contract - abi.encodeCall(_timelock.setGovernance, (address(_dualGovernance))), + abi.encodeCall(_timelock.setGovernance, (address(_dgDeployedContracts.dualGovernance))), // Now the emergency mode may be deactivated (all scheduled calls will be canceled) abi.encodeCall(_timelock.deactivateEmergencyMode, ()), // Setup emergency committee for some period of time until the Dual Governance is battle tested abi.encodeCall( - _timelock.setEmergencyProtectionActivationCommittee, (address(_emergencyActivationCommittee)) + _timelock.setEmergencyProtectionActivationCommittee, + (address(_dgDeployConfig.timelock.emergencyActivationCommittee)) ), abi.encodeCall( - _timelock.setEmergencyProtectionExecutionCommittee, (address(_emergencyExecutionCommittee)) + _timelock.setEmergencyProtectionExecutionCommittee, + (address(_dgDeployConfig.timelock.emergencyExecutionCommittee)) ), abi.encodeCall( - _timelock.setEmergencyProtectionEndDate, (_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now())) + _timelock.setEmergencyProtectionEndDate, + (_DEFAULT_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now())) ), - abi.encodeCall(_timelock.setEmergencyModeDuration, (_EMERGENCY_MODE_DURATION)) + abi.encodeCall(_timelock.setEmergencyModeDuration, (_DEFAULT_EMERGENCY_MODE_DURATION)) ] ); // The vote to launch Dual Governance is launched and reached the quorum (the major part of LDO holder still have power) uint256 dualGovernanceLunchProposalId = - _submitProposalViaTimelockedGovernance("Launch the Dual Governance", dualGovernanceLaunchCalls); + _submitProposal(dualGovernanceLaunchCalls, "Launch the Dual Governance"); // wait until the after submit delay has passed - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaTimelockedGovernance(dualGovernanceLunchProposalId, true); - _scheduleProposalViaTimelockedGovernance(dualGovernanceLunchProposalId); + _assertCanSchedule(dualGovernanceLunchProposalId, true); + _scheduleProposal(dualGovernanceLunchProposalId); _assertProposalScheduled(dualGovernanceLunchProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); // now emergency committee may execute the proposal - _executeEmergencyExecute(dualGovernanceLunchProposalId); + _emergencyExecute(dualGovernanceLunchProposalId); - assertEq(_timelock.getGovernance(), address(_dualGovernance)); + assertEq(_timelock.getGovernance(), address(_dgDeployedContracts.dualGovernance)); // TODO: check emergency protection also was applied // malicious proposal now cancelled @@ -178,21 +186,21 @@ contract PlanBSetup is ScenarioTestBlueprint { // ACT 4. 🫡 EMERGENCY COMMITTEE LIFETIME IS ENDED // --- { - _wait(_EMERGENCY_PROTECTION_DURATION.plusSeconds(1)); + _wait(_getEmergencyProtectionDuration().plusSeconds(1)); assertFalse(_timelock.isEmergencyProtectionEnabled()); - uint256 proposalId = _submitProposal( - _dualGovernance, "DAO continues regular staff on potentially dangerous contract", regularStaffCalls + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO continues regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); // but the call still not executable _assertCanExecute(proposalId, true); @@ -207,35 +215,44 @@ contract PlanBSetup is ScenarioTestBlueprint { { // some time later, the major Dual Governance update release is ready to be launched _wait(Durations.from(365 days)); - DualGovernance dualGovernanceV2 = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider + + DualGovernance dualGovernanceV2 = ContractsDeployment.deployDualGovernance({ + components: DualGovernance.DualGovernanceComponents({ + timelock: _timelock, + resealManager: _dgDeployedContracts.resealManager, + configProvider: _dgDeployedContracts.dualGovernanceConfigProvider + }), + signallingTokens: _dgDeployConfig.dualGovernance.signallingTokens, + sanityCheckParams: _dgDeployConfig.dualGovernance.sanityCheckParams }); ExternalCall[] memory dualGovernanceUpdateCalls = ExternalCallHelpers.create( [address(dualGovernanceV2), address(_timelock), address(_timelock), address(_timelock)], [ - abi.encodeCall(_dualGovernance.registerProposer, (address(_lido.voting), _timelock.getAdminExecutor())), + abi.encodeCall( + _dgDeployedContracts.dualGovernance.registerProposer, + (address(_lido.voting), _timelock.getAdminExecutor()) + ), // Update the controller for timelock abi.encodeCall(_timelock.setGovernance, address(dualGovernanceV2)), // Assembly the emergency committee again, until the new version of Dual Governance is battle tested abi.encodeCall( - _timelock.setEmergencyProtectionEndDate, (_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now())) + _timelock.setEmergencyProtectionEndDate, + (_DEFAULT_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now())) ), abi.encodeCall(_timelock.setEmergencyModeDuration, (Durations.from(30 days))) ] ); uint256 updateDualGovernanceProposalId = - _submitProposalViaDualGovernance("Update Dual Governance to V2", dualGovernanceUpdateCalls); + _submitProposalByAdminProposer(dualGovernanceUpdateCalls, "Update Dual Governance to V2"); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaDualGovernance(updateDualGovernanceProposalId, true); - _scheduleProposalViaDualGovernance(updateDualGovernanceProposalId); + _assertCanSchedule(updateDualGovernanceProposalId, true); + _scheduleProposal(updateDualGovernanceProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); // but the call still not executable _assertCanExecute(updateDualGovernanceProposalId, true); @@ -249,34 +266,39 @@ contract PlanBSetup is ScenarioTestBlueprint { assertFalse(_timelock.isEmergencyModeActive()); - emergencyState = _timelock.getEmergencyProtectionDetails(); - assertEq(_timelock.getEmergencyActivationCommittee(), address(_emergencyActivationCommittee)); - assertEq(_timelock.getEmergencyExecutionCommittee(), address(_emergencyExecutionCommittee)); - assertEq(emergencyState.emergencyModeDuration, Durations.from(30 days)); - assertEq(emergencyState.emergencyModeEndsAfter, Timestamps.ZERO); + assertEq( + _timelock.getEmergencyActivationCommittee(), + address(_dgDeployConfig.timelock.emergencyActivationCommittee) + ); + assertEq( + _timelock.getEmergencyExecutionCommittee(), + address(_dgDeployConfig.timelock.emergencyExecutionCommittee) + ); + assertEq(_getEmergencyModeDuration(), Durations.from(30 days)); + assertEq(_getEmergencyModeEndsAfter(), Timestamps.ZERO); // use the new version of the dual governance in the future calls - _dualGovernance = dualGovernanceV2; + _dgDeployedContracts.dualGovernance = dualGovernanceV2; } // --- // ACT 7. 📆 DAO CONTINUES THEIR REGULAR DUTIES (PROTECTED BY DUAL GOVERNANCE V2) // --- { - uint256 proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); // wait while the after schedule delay has passed - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); // execute the proposal _assertCanExecute(proposalId, true); @@ -296,10 +318,10 @@ contract PlanBSetup is ScenarioTestBlueprint { // schedule some malicious call uint256 maliciousProposalId; { - maliciousProposalId = _submitProposalViaTimelockedGovernance("Rug Pool attempt", maliciousCalls); + maliciousProposalId = _submitProposal(maliciousCalls, "Rug Pool attempt"); // malicious calls can't be executed until the delays have passed - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, false); + _assertCanSchedule(maliciousProposalId, false); } // activate emergency mode @@ -307,10 +329,7 @@ contract PlanBSetup is ScenarioTestBlueprint { { _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - assertTrue(_timelock.isEmergencyModeActive()); + _activateEmergencyMode(); } // delay for malicious proposal has passed, but it can't be executed because of emergency mode was activated @@ -318,9 +337,9 @@ contract PlanBSetup is ScenarioTestBlueprint { // the after submit delay has passed, and proposal can be scheduled, but not executed _wait(_timelock.getAfterScheduleDelay() + Durations.from(1 seconds)); _wait(_timelock.getAfterSubmitDelay().plusSeconds(1)); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, true); + _assertCanSchedule(maliciousProposalId, true); - _scheduleProposalViaTimelockedGovernance(maliciousProposalId); + _scheduleProposal(maliciousProposalId); _wait(_timelock.getAfterScheduleDelay().plusSeconds(1)); _assertCanExecute(maliciousProposalId, false); @@ -332,20 +351,19 @@ contract PlanBSetup is ScenarioTestBlueprint { // another malicious call is scheduled during the emergency mode also can't be executed uint256 anotherMaliciousProposalId; { - _wait(_EMERGENCY_MODE_DURATION.dividedBy(2)); + _wait(_getEmergencyModeDuration().dividedBy(2)); // emergency mode still active assertTrue(_timelock.getEmergencyProtectionDetails().emergencyModeEndsAfter > Timestamps.now()); - anotherMaliciousProposalId = - _submitProposalViaTimelockedGovernance("Another Rug Pool attempt", maliciousCalls); + anotherMaliciousProposalId = _submitProposal(maliciousCalls, "Another Rug Pool attempt"); // malicious calls can't be executed until the delays have passed _assertCanExecute(anotherMaliciousProposalId, false); // the after submit delay has passed, and proposal can not be executed _wait(_timelock.getAfterSubmitDelay().plusSeconds(1)); - _assertCanScheduleViaTimelockedGovernance(anotherMaliciousProposalId, true); + _assertCanSchedule(anotherMaliciousProposalId, true); _wait(_timelock.getAfterScheduleDelay().plusSeconds(1)); _assertCanExecute(anotherMaliciousProposalId, false); @@ -356,7 +374,7 @@ contract PlanBSetup is ScenarioTestBlueprint { // emergency mode is over but proposals can't be executed until the emergency mode turned off manually { - _wait(_EMERGENCY_MODE_DURATION.dividedBy(2)); + _wait(_getEmergencyModeDuration().dividedBy(2)); assertTrue(emergencyState.emergencyModeEndsAfter < Timestamps.now()); vm.expectRevert(abi.encodeWithSelector(EmergencyProtection.UnexpectedEmergencyModeState.selector, true)); @@ -400,65 +418,46 @@ contract PlanBSetup is ScenarioTestBlueprint { function testFork_EmergencyResetGovernance() external { // deploy dual governance full setup { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); + _deployDGSetup({isEmergencyProtectionEnabled: true}); assertNotEq(_timelock.getGovernance(), _timelock.getEmergencyGovernance()); } // emergency committee activates emergency mode { - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - assertTrue(_timelock.isEmergencyModeActive()); + _activateEmergencyMode(); } // before the end of the emergency mode emergency committee can reset the controller to // disable dual governance { - _wait(_EMERGENCY_MODE_DURATION.dividedBy(2)); - - IEmergencyProtectedTimelock.EmergencyProtectionDetails memory emergencyState = - _timelock.getEmergencyProtectionDetails(); - - assertTrue(emergencyState.emergencyModeEndsAfter > Timestamps.now()); + _wait(_getEmergencyModeDuration().dividedBy(2)); - _executeEmergencyReset(); + assertTrue(_getEmergencyModeEndsAfter() > Timestamps.now()); - assertEq(_timelock.getGovernance(), _timelock.getEmergencyGovernance()); - - emergencyState = _timelock.getEmergencyProtectionDetails(); - assertEq(_timelock.getEmergencyActivationCommittee(), address(0)); - assertEq(_timelock.getEmergencyExecutionCommittee(), address(0)); - assertEq(emergencyState.emergencyModeDuration, Durations.ZERO); - assertEq(emergencyState.emergencyModeEndsAfter, Timestamps.ZERO); - assertFalse(_timelock.isEmergencyModeActive()); + _emergencyReset(); } } function testFork_ExpiredEmergencyCommitteeHasNoPower() external { // deploy dual governance full setup { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); + _deployDGSetup({isEmergencyProtectionEnabled: true}); assertNotEq(_timelock.getGovernance(), _timelock.getEmergencyGovernance()); } // wait till the protection duration passes { - _wait(_EMERGENCY_PROTECTION_DURATION.plusSeconds(1)); + _wait(_getEmergencyModeDuration().plusSeconds(1)); } - IEmergencyProtectedTimelock.EmergencyProtectionDetails memory emergencyState = - _timelock.getEmergencyProtectionDetails(); - // attempt to activate emergency protection fails { vm.expectRevert( abi.encodeWithSelector( - EmergencyProtection.EmergencyProtectionExpired.selector, emergencyState.emergencyProtectionEndsAfter + EmergencyProtection.EmergencyProtectionExpired.selector, _getEmergencyProtectionEndsAfter() ) ); - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); + this.external__activateEmergencyMode(); } } } diff --git a/test/scenario/happy-path.t.sol b/test/scenario/happy-path.t.sol index 0bf8ec82..b6d8d2c7 100644 --- a/test/scenario/happy-path.t.sol +++ b/test/scenario/happy-path.t.sol @@ -4,24 +4,25 @@ pragma solidity 0.8.26; import {EvmScriptUtils} from "../utils/evm-script-utils.sol"; import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; -import {ExternalCall, ExternalCallHelpers, ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; +import {ExternalCall, ExternalCallHelpers} from "../utils/executor-calls.sol"; +import {DGRegressionTestSetup} from "../utils/integration-tests.sol"; import {ExecutableProposals} from "contracts/libraries/ExecutableProposals.sol"; import {LidoUtils, EvmScriptUtils} from "../utils/lido-utils.sol"; -contract HappyPathTest is ScenarioTestBlueprint { +contract HappyPathTest is DGRegressionTestSetup { using LidoUtils for LidoUtils.Context; function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _loadOrDeployDGSetup(); } function testFork_HappyPath() external { ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - uint256 proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); @@ -30,72 +31,21 @@ contract HappyPathTest is ScenarioTestBlueprint { // the min execution delay hasn't elapsed yet vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); + this.external__scheduleProposal(proposalId); // wait till the first phase of timelock passes - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); _executeProposal(proposalId); - _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); - } - - function testFork_HappyPathWithMultipleItems() external { - // additional phase required here, grant rights to call DAO Agent to the admin executor - _lido.grantPermission(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE(), _timelock.getAdminExecutor()); - - bytes memory agentDoRegularStaffPayload = abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (42)); - bytes memory targetCallEvmScript = - EvmScriptUtils.encodeEvmCallScript(address(_targetMock), agentDoRegularStaffPayload); - - ExternalCall[] memory multipleCalls = ExternalCallHelpers.create( - [address(_lido.agent), address(_targetMock)], - [ - abi.encodeCall(_lido.agent.forward, (targetCallEvmScript)), - abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (43)) - ] - ); - - uint256 proposalId = _submitProposal(_dualGovernance, "Multiple items", multipleCalls); - - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - - // proposal can't be scheduled before the after submit delay has passed - _assertCanScheduleViaDualGovernance(proposalId, false); - - // the min execution delay hasn't elapsed yet - vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); - - // wait till the DG-enforced timelock elapses - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); - _assertProposalScheduled(proposalId); - - _waitAfterScheduleDelayPassed(); - - _assertCanExecute(proposalId, true); - _executeProposal(proposalId); - - address[] memory senders = new address[](2); - senders[0] = address(_lido.agent); - senders[1] = _timelock.getAdminExecutor(); - - ExternalCall[] memory expectedTargetCalls = ExternalCallHelpers.create( - [address(_lido.agent), address(_targetMock)], - [agentDoRegularStaffPayload, abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (43))] - ); - - _assertTargetMockCalls(senders, expectedTargetCalls); + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); } // TODO: make this test pass diff --git a/test/scenario/last-moment-malicious-proposal.t.sol b/test/scenario/last-moment-malicious-proposal.t.sol index 7d4f6503..3a90a33e 100644 --- a/test/scenario/last-moment-malicious-proposal.t.sol +++ b/test/scenario/last-moment-malicious-proposal.t.sol @@ -1,101 +1,87 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; +import {Durations} from "contracts/types/Duration.sol"; import {PercentsD16} from "contracts/types/PercentD16.sol"; import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; import {DualGovernance} from "contracts/DualGovernance.sol"; -import { - ScenarioTestBlueprint, ExternalCall, ExternalCallHelpers, Durations -} from "../utils/scenario-test-blueprint.sol"; +import {DGScenarioTestSetup, ExternalCallHelpers, ExternalCall, Proposers} from "../utils/integration-tests.sol"; -contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { +contract LastMomentMaliciousProposalSuccessor is DGScenarioTestSetup { function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _deployDGSetup({isEmergencyProtectionEnabled: false}); } function testFork_LastMomentMaliciousProposal() external { ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); uint256 proposalId; - _step("1. DAO SUBMITS PROPOSAL WITH REGULAR STAFF"); + _step("1. DAO submits proposal with regular staff"); { - proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _logVetoSignallingState(); } address maliciousActor = makeAddr("MALICIOUS_ACTOR"); _setupStETHBalance(maliciousActor, PercentsD16.fromBasisPoints(15_00)); - _step("2. MALICIOUS ACTOR STARTS ACQUIRE VETO SIGNALLING DURATION"); + _step("2. Malicious actor starts acquire veto signalling duration"); { _lockStETH(maliciousActor, PercentsD16.fromBasisPoints(12_00)); _assertVetoSignalingState(); - _logVetoSignallingState(); // almost all veto signalling period has passed _wait(Durations.from(20 days)); _activateNextState(); _assertVetoSignalingState(); - _logVetoSignallingState(); } uint256 maliciousProposalId; - _step("3. MALICIOUS ACTOR SUBMITS MALICIOUS PROPOSAL"); + _step("3. Malicious actor submits malicious proposal"); { _assertVetoSignalingState(); - maliciousProposalId = _submitProposal( - _dualGovernance, - "Malicious Proposal", + maliciousProposalId = _submitProposalByAdminProposer( ExternalCallHelpers.create( address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doRugPool, ()) - ) + ), + "Malicious Proposal" ); // the both calls aren't executable until the delay has passed _assertProposalSubmitted(proposalId); _assertProposalSubmitted(maliciousProposalId); - _logVetoSignallingState(); } - _step("4. MALICIOUS ACTOR UNLOCK FUNDS FROM ESCROW"); + _step("4. Malicious actor unlock funds from escrow"); { _wait(Durations.from(12 seconds)); _unlockStETH(maliciousActor); - _assertVetoSignalingDeactivationState(); - _logVetoSignallingDeactivationState(); + _assertVetoSignallingDeactivationState(); } address stEthHolders = makeAddr("STETH_WHALE"); - _setupStETHBalance( - stEthHolders, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); - _step("5. STETH HOLDERS ACQUIRING QUORUM TO VETO MALICIOUS PROPOSAL"); + _setupStETHBalance(stEthHolders, _getFirstSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); + _step("5. StETH holders acquiring quorum to veto malicious proposal"); { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().dividedBy(2)); - _lockStETH( - stEthHolders, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1) - ); - _assertVetoSignalingDeactivationState(); - _logVetoSignallingDeactivationState(); + _wait(_getVetoSignallingDeactivationMaxDuration().dividedBy(2)); + _lockStETH(stEthHolders, _getFirstSealRageQuitSupport() + PercentsD16.fromBasisPoints(1)); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().dividedBy(2).plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().dividedBy(2).plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); } - _step("6. MALICIOUS PROPOSAL CAN'T BE EXECUTED IN THE VETO COOLDOWN STATE"); + _step("6. Malicious proposal can't be executed in the veto cooldown state"); { // the regular proposal can be executed - _scheduleProposalViaDualGovernance(proposalId); - _waitAfterScheduleDelayPassed(); + _scheduleProposal(proposalId); + _wait(_getAfterScheduleDelay()); _executeProposal(proposalId); _assertProposalExecuted(proposalId); @@ -103,33 +89,30 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { vm.expectRevert( abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, maliciousProposalId) ); - this.scheduleProposalExternal(maliciousProposalId); + this.external__scheduleProposal(maliciousProposalId); _assertProposalSubmitted(maliciousProposalId); } - _step("7. NEW VETO SIGNALLING ROUND FOR MALICIOUS PROPOSAL IS STARTED"); + _step("7. New veto signalling round for malicious proposal is started"); { - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertVetoSignalingState(); - _logVetoSignallingState(); // the second seal rage quit support is reached - _setupStETHBalance(stEthHolders, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); - _lockStETH(stEthHolders, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); + _setupStETHBalance(stEthHolders, _getSecondSealRageQuitSupport()); + _lockStETH(stEthHolders, _getSecondSealRageQuitSupport()); _assertVetoSignalingState(); - _logVetoSignallingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); - _logVetoSignallingState(); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); _assertRageQuitState(); vm.expectRevert( abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, maliciousProposalId) ); - this.scheduleProposalExternal(maliciousProposalId); + this.external__scheduleProposal(maliciousProposalId); } } @@ -141,12 +124,11 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { // ACT 1. DAO SUBMITS CONTROVERSIAL PROPOSAL // --- { - proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _logVetoSignallingState(); } // --- @@ -155,10 +137,7 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { address maliciousActor = makeAddr("MALICIOUS_ACTOR"); { _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - _setupStETHBalance( - maliciousActor, - _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); + _setupStETHBalance(maliciousActor, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); _lockStETH(maliciousActor, PercentsD16.fromBasisPoints(12_00)); _assertVetoSignalingState(); @@ -166,27 +145,26 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { _assertProposalSubmitted(proposalId); - (, uint256 currentVetoSignallingDuration,,) = _getVetoSignallingState(); - _wait(Durations.from(currentVetoSignallingDuration + 1)); + _wait(_getVetoSignallingDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); + _assertVetoSignallingDeactivationState(); } // --- // ACT 3. THE VETO SIGNALLING DEACTIVATION DURATION EQUALS TO "VETO_SIGNALLING_DEACTIVATION_MAX_DURATION" DAYS // --- { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); _executeProposal(proposalId); @@ -197,60 +175,53 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { function testFork_VetoSignallingToNormalState() external { address maliciousActor = makeAddr("MALICIOUS_ACTOR"); - _setupStETHBalance( - maliciousActor, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); - _step("2. MALICIOUS ACTOR LOCKS FIRST SEAL THRESHOLD TO ACTIVATE VETO SIGNALLING BEFORE PROPOSAL SUBMISSION"); + _setupStETHBalance(maliciousActor, _getFirstSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); + _step("2. Malicious actor locks first seal threshold to activate veto signalling before proposal submission"); { - _lockStETH( - maliciousActor, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1) - ); + _lockStETH(maliciousActor, _getFirstSealRageQuitSupport()); _assertVetoSignalingState(); - _logVetoSignallingState(); } uint256 proposalId; ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - _step("2. DAO SUBMITS PROPOSAL WITH REGULAR STAFF"); + _step("2. DAO submits proposal with regular staff"); { - proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + _wait(_getVetoSignallingDuration().dividedBy(2)); + + proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _logVetoSignallingState(); } - _step("3. THE VETO SIGNALLING & DEACTIVATION PASSED BUT PROPOSAL STILL NOT EXECUTABLE"); + _step("3. The veto Signalling & Deactivation passed but proposal still not executable"); { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); - _logVetoSignallingDeactivationState(); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); vm.expectRevert(abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, proposalId)); - this.scheduleProposalExternal(proposalId); + this.external__scheduleProposal(proposalId); } - _step("4. AFTER THE VETO COOLDOWN GOVERNANCE TRANSITIONS INTO NORMAL STATE"); + _step("4. After the VetoCooldown governance transitions into Normal state"); { _unlockStETH(maliciousActor); - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertNormalState(); } - _step("5. PROPOSAL EXECUTABLE IN THE NORMAL STATE"); + _step("5. Proposal executable in the normal state"); { - _scheduleProposalViaDualGovernance(proposalId); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(proposalId); _assertProposalExecuted(proposalId); } @@ -258,78 +229,64 @@ contract LastMomentMaliciousProposalSuccessor is ScenarioTestBlueprint { function testFork_ProposalSubmissionFrontRunning() external { address maliciousActor = makeAddr("MALICIOUS_ACTOR"); - _step("2. MALICIOUS ACTOR LOCKS FIRST SEAL THRESHOLD TO ACTIVATE VETO SIGNALLING BEFORE PROPOSAL SUBMISSION"); + _step("2. Malicious actor locks first seal threshold to activate VetoSignalling before proposal submission"); { - _setupStETHBalance( - maliciousActor, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); - _lockStETH( - maliciousActor, - _dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1) - ); + _setupStETHBalance(maliciousActor, _getFirstSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); + _lockStETH(maliciousActor, _getFirstSealRageQuitSupport() + PercentsD16.fromBasisPoints(1)); _assertVetoSignalingState(); - _logVetoSignallingState(); } uint256 proposalId; ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - _step("2. DAO SUBMITS PROPOSAL WITH REGULAR STAFF"); + _step("2. DAO submits proposal with regular staff"); { - proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + _wait(_getVetoSignallingDuration().dividedBy(2)); + proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); - _logVetoSignallingState(); } - _step("3. THE VETO SIGNALLING & DEACTIVATION PASSED BUT PROPOSAL STILL NOT EXECUTABLE"); + _step("3. The VetoSignalling & Deactivation passed but proposal still not executable"); { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDuration().plusSeconds(1)); _activateNextState(); - _assertVetoSignalingDeactivationState(); - _logVetoSignallingDeactivationState(); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); vm.expectRevert(abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, proposalId)); - this.scheduleProposalExternal(proposalId); + this.external__scheduleProposal(proposalId); } - _step("4. AFTER THE VETO COOLDOWN NEW VETO SIGNALLING ROUND STARTED"); + _step("4. After the VetoCooldown new VetoSignalling round started"); { - _wait(_dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION().plusSeconds(1)); + _wait(_getVetoCooldownDuration().plusSeconds(1)); _activateNextState(); _assertVetoSignalingState(); - _logVetoSignallingState(); vm.expectRevert(abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, proposalId)); - this.scheduleProposalExternal(proposalId); + this.external__scheduleProposal(proposalId); } - _step("5. PROPOSAL EXECUTABLE IN THE NEXT VETO COOLDOWN"); + _step("5. Proposal executable in the next VetoCooldown"); { - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION().multipliedBy(2)); + _wait(_getVetoSignallingMinDuration().multipliedBy(2)); _activateNextState(); - _assertVetoSignalingDeactivationState(); - _logVetoSignallingDeactivationState(); + _assertVetoSignallingDeactivationState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingDeactivationMaxDuration().plusSeconds(1)); _activateNextState(); _assertVetoCooldownState(); - _scheduleProposalViaDualGovernance(proposalId); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(proposalId); _assertProposalExecuted(proposalId); } } - - function scheduleProposalExternal(uint256 proposalId) external { - _scheduleProposalViaDualGovernance(proposalId); - } } diff --git a/test/scenario/launch-happy-path.t.sol b/test/scenario/launch-happy-path.t.sol deleted file mode 100644 index 4fba2076..00000000 --- a/test/scenario/launch-happy-path.t.sol +++ /dev/null @@ -1,390 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; -/* solhint-disable no-console */ - -import {DeployConfig, LidoContracts} from "scripts/deploy/config/Config.sol"; -import {DeployedContracts} from "scripts/deploy/DeployedContractsSet.sol"; -import {DeployVerification} from "scripts/deploy/DeployVerification.sol"; -import {DeployVerifier} from "scripts/launch/DeployVerifier.sol"; - -import {Durations} from "contracts/types/Duration.sol"; -import {PercentsD16} from "contracts/types/PercentD16.sol"; - -import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; - -import {IStETH} from "contracts/interfaces/IStETH.sol"; -import {IWstETH} from "contracts/interfaces/IWstETH.sol"; -import {IGovernance} from "contracts/interfaces/IDualGovernance.sol"; -import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; - -import {IWithdrawalQueue} from "test/utils/interfaces/IWithdrawalQueue.sol"; -import {IAragonVoting} from "test/utils/interfaces/IAragonVoting.sol"; -import {IAragonAgent, IAragonForwarder} from "test/utils/interfaces/IAragonAgent.sol"; -import {IAragonACL} from "test/utils/interfaces/IAragonACL.sol"; - -import {ExternalCall, ExternalCallHelpers, ScenarioTestBlueprint} from "test/utils/scenario-test-blueprint.sol"; -import {LidoUtils} from "test/utils/lido-utils.sol"; -import {EvmScriptUtils} from "test/utils/evm-script-utils.sol"; - -import {ST_ETH, WST_ETH, WITHDRAWAL_QUEUE, DAO_VOTING, DAO_ACL, DAO_AGENT} from "addresses/mainnet-addresses.sol"; - -import {IAccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; -import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; - -import {console} from "forge-std/console.sol"; - -contract DeployHappyPath is ScenarioTestBlueprint { - using LidoUtils for LidoUtils.Context; - - //Emergency committee - LidoUtils.Context internal lidoUtils = LidoUtils.mainnet(); - address _ldoHolder = address(0xF977814e90dA44bFA03b6295A0616a897441aceC); - DeployVerifier internal _verifier; - RolesVerifier internal _rolesVerifier; - - function setUp() external { - _deployDualGovernanceSetup(true, true); - } - - function testFork_dualGovernance_deployment_and_activation() external { - // Deploy Dual Governance contracts - - _verifier = new DeployVerifier(_dgDeployConfig, _lidoAddresses); - - // Verify deployment - _verifier.verify(_contracts, false); - - // Activate Dual Governance Emergency Mode - vm.prank(_emergencyActivationCommittee); - _contracts.timelock.activateEmergencyMode(); - - assertEq(_contracts.timelock.isEmergencyModeActive(), true, "Emergency mode is not active"); - - // Emergency Committee execute emergencyReset() - - vm.prank(_emergencyExecutionCommittee); - _contracts.timelock.emergencyReset(); - - assertEq( - _contracts.timelock.getGovernance(), - address(_contracts.temporaryEmergencyGovernance), - "Incorrect governance address in EmergencyProtectedTimelock" - ); - - // Propose to set Governance, Activation Committee, Execution Committee, Emergency Mode End Date and Emergency Mode Duration - ExternalCall[] memory calls; - uint256 emergencyProtectionEndsAfter = _dgDeployConfig.EMERGENCY_PROTECTION_END_DATE.toSeconds(); - calls = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setGovernance.selector, address(_contracts.dualGovernance) - ) - }), - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setEmergencyGovernance.selector, address(_contracts.emergencyGovernance) - ) - }), - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setEmergencyProtectionActivationCommittee.selector, _emergencyActivationCommittee - ) - }), - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setEmergencyProtectionExecutionCommittee.selector, _emergencyExecutionCommittee - ) - }), - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setEmergencyProtectionEndDate.selector, emergencyProtectionEndsAfter - ) - }), - ExternalCall({ - target: address(_contracts.timelock), - value: 0, - payload: abi.encodeWithSelector( - _contracts.timelock.setEmergencyModeDuration.selector, _dgDeployConfig.EMERGENCY_MODE_DURATION - ) - }) - ] - ); - console.log("Calls to set DG state:"); - console.logBytes(abi.encode(calls)); - - console.log("Submit proposal to set DG state calldata"); - console.logBytes( - abi.encodeWithSelector( - _contracts.temporaryEmergencyGovernance.submitProposal.selector, - calls, - "Reset emergency mode and set original DG as governance" - ) - ); - vm.prank(_temporaryEmergencyGovernanceProposer); - uint256 proposalId = _contracts.temporaryEmergencyGovernance.submitProposal( - calls, "Reset emergency mode and set original DG as governance" - ); - - // Schedule and execute the proposal - _wait(_dgDeployConfig.AFTER_SUBMIT_DELAY); - _contracts.temporaryEmergencyGovernance.scheduleProposal(proposalId); - _wait(_dgDeployConfig.AFTER_SCHEDULE_DELAY); - _contracts.timelock.execute(proposalId); - - // Verify state after proposal execution - assertEq( - _contracts.timelock.getGovernance(), - address(_contracts.dualGovernance), - "Incorrect governance address in EmergencyProtectedTimelock" - ); - assertEq( - _contracts.timelock.getEmergencyGovernance(), - address(_contracts.emergencyGovernance), - "Incorrect governance address in EmergencyProtectedTimelock" - ); - assertEq(_contracts.timelock.isEmergencyModeActive(), false, "Emergency mode is not active"); - assertEq( - _contracts.timelock.getEmergencyActivationCommittee(), - _emergencyActivationCommittee, - "Incorrect emergencyActivationCommittee address in EmergencyProtectedTimelock" - ); - assertEq( - _contracts.timelock.getEmergencyExecutionCommittee(), - _emergencyExecutionCommittee, - "Incorrect emergencyExecutionCommittee address in EmergencyProtectedTimelock" - ); - - IEmergencyProtectedTimelock.EmergencyProtectionDetails memory details = - _contracts.timelock.getEmergencyProtectionDetails(); - assertEq( - details.emergencyModeDuration, - _dgDeployConfig.EMERGENCY_MODE_DURATION, - "Incorrect emergencyModeDuration in EmergencyProtectedTimelock" - ); - assertEq( - details.emergencyModeEndsAfter.toSeconds(), - 0, - "Incorrect emergencyModeEndsAfter in EmergencyProtectedTimelock" - ); - assertEq( - details.emergencyProtectionEndsAfter.toSeconds(), - emergencyProtectionEndsAfter, - "Incorrect emergencyProtectionEndsAfter in EmergencyProtectedTimelock" - ); - - // Activate Dual Governance with DAO Voting - - // Prepare RolesVerifier - address[] memory ozContracts = new address[](1); - RolesVerifier.OZRoleInfo[] memory roles = new RolesVerifier.OZRoleInfo[](2); - address[] memory pauseRoleHolders = new address[](2); - pauseRoleHolders[0] = address(0x79243345eDbe01A7E42EDfF5900156700d22611c); - pauseRoleHolders[1] = address(_contracts.resealManager); - address[] memory resumeRoleHolders = new address[](1); - resumeRoleHolders[0] = address(_contracts.resealManager); - - ozContracts[0] = WITHDRAWAL_QUEUE; - - roles[0] = RolesVerifier.OZRoleInfo({ - role: IWithdrawalQueue(WITHDRAWAL_QUEUE).PAUSE_ROLE(), - accounts: pauseRoleHolders - }); - roles[1] = RolesVerifier.OZRoleInfo({ - role: IWithdrawalQueue(WITHDRAWAL_QUEUE).RESUME_ROLE(), - accounts: resumeRoleHolders - }); - - _rolesVerifier = new RolesVerifier(ozContracts, roles); - - // DAO Voting to activate Dual Governance - { - // Prepare calls to execute by Agent - ExternalCall[] memory roleGrantingCalls; - roleGrantingCalls = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(_lidoAddresses.withdrawalQueue), - value: 0, - payload: abi.encodeWithSelector( - IAccessControl.grantRole.selector, - IWithdrawalQueue(WITHDRAWAL_QUEUE).PAUSE_ROLE(), - address(_contracts.resealManager) - ) - }), - ExternalCall({ - target: address(_lidoAddresses.withdrawalQueue), - value: 0, - payload: abi.encodeWithSelector( - IAccessControl.grantRole.selector, - IWithdrawalQueue(WITHDRAWAL_QUEUE).RESUME_ROLE(), - address(_contracts.resealManager) - ) - }), - ExternalCall({ - target: address(DAO_ACL), - value: 0, - payload: abi.encodeWithSelector( - IAragonACL.grantPermission.selector, - _contracts.adminExecutor, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ) - }) - ] - ); - - // Propose to revoke Agent forward permission from Voting - ExternalCall[] memory revokeAgentForwardCall; - revokeAgentForwardCall = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(DAO_ACL), - value: 0, - payload: abi.encodeWithSelector( - IAragonACL.revokePermission.selector, - DAO_VOTING, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ) - }) - ] - ); - - ExternalCall[] memory revokeAgentForwardCallDualGovernanceProposal; - revokeAgentForwardCallDualGovernanceProposal = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(lidoUtils.agent), - value: 0, - payload: abi.encodeWithSelector( - IAragonForwarder.forward.selector, _encodeExternalCalls(revokeAgentForwardCall) - ) - }) - ] - ); - - // Prepare calls to execute Voting - bytes memory setPermissionPayload = abi.encodeWithSelector( - IAragonACL.setPermissionManager.selector, - DAO_AGENT, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ); - - bytes memory forwardRolePayload = - abi.encodeWithSelector(IAragonForwarder.forward.selector, _encodeExternalCalls(roleGrantingCalls)); - - bytes memory verifyPayload = abi.encodeWithSelector(DeployVerifier.verify.selector, _contracts, true); - - bytes memory verifyOZRolesPayload = abi.encodeWithSelector(RolesVerifier.verifyOZRoles.selector); - - bytes memory submitProposalPayload = abi.encodeWithSelector( - IGovernance.submitProposal.selector, - revokeAgentForwardCallDualGovernanceProposal, - "Revoke Agent forward permission from Voting" - ); - - ExternalCall[] memory activateCalls = ExternalCallHelpers.create( - [ - ExternalCall({target: address(DAO_ACL), value: 0, payload: setPermissionPayload}), - ExternalCall({target: address(lidoUtils.agent), value: 0, payload: forwardRolePayload}), - ExternalCall({target: address(_verifier), value: 0, payload: verifyPayload}), - ExternalCall({target: address(_rolesVerifier), value: 0, payload: verifyOZRolesPayload}), - ExternalCall({target: address(_contracts.dualGovernance), value: 0, payload: submitProposalPayload}) - ] - ); - - // Create and execute vote to activate Dual Governance - uint256 voteId = lidoUtils.adoptVote("Dual Governance activation vote", _encodeExternalCalls(activateCalls)); - lidoUtils.executeVote(voteId); - - uint256 expectedProposalId = 2; - - // Schedule and execute the proposal - _wait(_dgDeployConfig.AFTER_SUBMIT_DELAY); - _contracts.dualGovernance.scheduleProposal(expectedProposalId); - _wait(_dgDeployConfig.AFTER_SCHEDULE_DELAY); - _contracts.timelock.execute(expectedProposalId); - - // Verify that Voting has no permission to forward to Agent - ExternalCall[] memory someAgentForwardCall; - someAgentForwardCall = ExternalCallHelpers.create( - [ - ExternalCall({ - target: address(DAO_ACL), - value: 0, - payload: abi.encodeWithSelector( - IAragonACL.revokePermission.selector, - _contracts.adminExecutor, - DAO_AGENT, - IAragonAgent(DAO_AGENT).RUN_SCRIPT_ROLE() - ) - }) - ] - ); - - vm.expectRevert("AGENT_CAN_NOT_FORWARD"); - vm.prank(DAO_VOTING); - IAragonForwarder(DAO_AGENT).forward(_encodeExternalCalls(someAgentForwardCall)); - } - } - - function _encodeExternalCalls(ExternalCall[] memory calls) internal pure returns (bytes memory result) { - result = abi.encodePacked(bytes4(uint32(1))); - - for (uint256 i = 0; i < calls.length; ++i) { - ExternalCall memory call = calls[i]; - result = abi.encodePacked(result, bytes20(call.target), bytes4(uint32(call.payload.length)), call.payload); - } - } -} - -contract RolesVerifier { - struct OZRoleInfo { - bytes32 role; - address[] accounts; - } - - mapping(address => OZRoleInfo[]) public ozContractRoles; - address[] private _ozContracts; - - constructor(address[] memory ozContracts, OZRoleInfo[] memory roles) { - _ozContracts = ozContracts; - - for (uint256 i = 0; i < ozContracts.length; ++i) { - for (uint256 r = 0; r < roles.length; ++r) { - ozContractRoles[ozContracts[i]].push(); - uint256 lastIndex = ozContractRoles[ozContracts[i]].length - 1; - ozContractRoles[ozContracts[i]][lastIndex].role = roles[r].role; - address[] memory accounts = roles[r].accounts; - for (uint256 a = 0; a < accounts.length; ++a) { - ozContractRoles[ozContracts[i]][lastIndex].accounts.push(accounts[a]); - } - } - } - } - - function verifyOZRoles() external view { - for (uint256 i = 0; i < _ozContracts.length; ++i) { - OZRoleInfo[] storage roles = ozContractRoles[_ozContracts[i]]; - for (uint256 j = 0; j < roles.length; ++j) { - AccessControlEnumerable accessControl = AccessControlEnumerable(_ozContracts[i]); - assert(accessControl.getRoleMemberCount(roles[j].role) == roles[j].accounts.length); - for (uint256 k = 0; k < roles[j].accounts.length; ++k) { - assert(accessControl.hasRole(roles[j].role, roles[j].accounts[k]) == true); - } - } - } - } -} diff --git a/test/scenario/proposal-deployment-modes.t.sol b/test/scenario/proposal-deployment-modes.t.sol index e48712b1..8fc69031 100644 --- a/test/scenario/proposal-deployment-modes.t.sol +++ b/test/scenario/proposal-deployment-modes.t.sol @@ -3,26 +3,28 @@ pragma solidity 0.8.26; import {ExecutableProposals} from "contracts/libraries/ExecutableProposals.sol"; -import {ScenarioTestBlueprint, ExternalCall} from "../utils/scenario-test-blueprint.sol"; +import {DGScenarioTestSetup, ExternalCall} from "../utils/integration-tests.sol"; -contract ProposalDeploymentModesTest is ScenarioTestBlueprint { - function test_regular_deployment_mode() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); +contract ProposalDeploymentModesScenarioTest is DGScenarioTestSetup { + function setUp() external {} + + function testFork_RegularDeploymentMode() external { + _deployDGSetup({isEmergencyProtectionEnabled: false}); (uint256 proposalId, ExternalCall[] memory regularStaffCalls) = _createAndAssertProposal(); _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); + this.external__scheduleProposal(proposalId); _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); _executeProposal(proposalId); @@ -30,109 +32,100 @@ contract ProposalDeploymentModesTest is ScenarioTestBlueprint { _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); } - function test_protected_deployment_mode_execute_after_timelock() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); + function testFork_ProtectedDeploymentMode_ExecuteAfterTimelock() external { + _deployDGSetup({isEmergencyProtectionEnabled: true}); (uint256 proposalId, ExternalCall[] memory regularStaffCalls) = _createAndAssertProposal(); _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); + this.external__scheduleProposal(proposalId); _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); _executeProposal(proposalId); - _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); } - function test_protected_deployment_mode_execute_in_emergency_mode() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: true}); + function testFork_ProtectedDeploymentMode_ExecuteInEmergencyMode() external { + _deployDGSetup({isEmergencyProtectionEnabled: true}); (uint256 proposalId, ExternalCall[] memory regularStaffCalls) = _createAndAssertProposal(); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); + _wait(_getAfterSubmitDelay().dividedBy(2)); vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); + this.external__scheduleProposal(proposalId); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - assertEq(_timelock.isEmergencyModeActive(), true); + _activateEmergencyMode(); _assertCanExecute(proposalId, false); - vm.prank(address(_emergencyExecutionCommittee)); - _timelock.emergencyExecute(proposalId); - - _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); + _emergencyExecute(proposalId); + _assertTargetMockCalls(_getAdminExecutor(), regularStaffCalls); } - function test_protected_deployment_mode_deactivation_in_emergency_mode() external { - _deployDualGovernanceSetup(true); + function testFork_ProtectedDeploymentMode_DeactivationInEmergencyMode() external { + _deployDGSetup({isEmergencyProtectionEnabled: true}); (uint256 proposalId,) = _createAndAssertProposal(); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); + _wait(_getAfterSubmitDelay().dividedBy(2)); vm.expectRevert(abi.encodeWithSelector(ExecutableProposals.AfterSubmitDelayNotPassed.selector, (proposalId))); - _scheduleProposalViaDualGovernance(proposalId); + this.external__scheduleProposal(proposalId); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaDualGovernance(proposalId, true); - _scheduleProposalViaDualGovernance(proposalId); + _assertCanSchedule(proposalId, true); + _scheduleProposal(proposalId); _assertProposalScheduled(proposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(proposalId, true); - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); + _activateEmergencyMode(); - assertEq(_timelock.isEmergencyModeActive(), true); - assertEq(_timelock.isEmergencyProtectionEnabled(), true); _assertCanExecute(proposalId, false); - // emergency protection disabled after emergency mode is activated - - _wait(_timelock.getEmergencyProtectionDetails().emergencyModeDuration.plusSeconds(1)); + // emergency protection may be disabled by anyone when full emergency mode duration has passed + _wait(_getEmergencyModeDuration().plusSeconds(1)); - assertEq(_timelock.isEmergencyModeActive(), true); - assertEq(_timelock.isEmergencyProtectionEnabled(), true); + assertEq(_isEmergencyModeActive(), true); + assertEq(_isEmergencyProtectionEnabled(), true); _timelock.deactivateEmergencyMode(); - assertEq(_timelock.isEmergencyModeActive(), false); - assertEq(_timelock.isEmergencyProtectionEnabled(), false); + assertEq(_isEmergencyModeActive(), false); + assertEq(_isEmergencyProtectionEnabled(), false); _assertCanExecute(proposalId, false); } function _createAndAssertProposal() internal returns (uint256, ExternalCall[] memory) { ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - uint256 proposalId = _submitProposal( - _dualGovernance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls + uint256 proposalId = _submitProposalByAdminProposer( + regularStaffCalls, "DAO does regular staff on potentially dangerous contract" ); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, regularStaffCalls); diff --git a/test/scenario/tiebreaker.t.sol b/test/scenario/tiebreaker.t.sol deleted file mode 100644 index 56854e98..00000000 --- a/test/scenario/tiebreaker.t.sol +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {Durations} from "contracts/types/Duration.sol"; -import {PercentsD16} from "contracts/types/PercentD16.sol"; - -import {ScenarioTestBlueprint, ExternalCall, ExternalCallHelpers} from "../utils/scenario-test-blueprint.sol"; - -contract TiebreakerScenarioTest is ScenarioTestBlueprint { - address internal immutable _VETOER = makeAddr("VETOER"); - uint256 public constant PAUSE_INFINITELY = type(uint256).max; - - function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); - _setupStETHBalance( - _VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); - } - - function test_proposal_approval() external { - uint256 quorum; - uint256 support; - bool isExecuted; - - address[] memory members; - - // Tiebreak activation - _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); - _lockStETH(_VETOER, 1 gwei); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); - _activateNextState(); - _assertRageQuitState(); - _wait(_dualGovernance.getTiebreakerDetails().tiebreakerActivationTimeout); - _activateNextState(); - - ExternalCall[] memory proposalCalls = ExternalCallHelpers.create(address(0), new bytes(0)); - uint256 proposalIdToExecute = _submitProposal(_dualGovernance, "Proposal for execution", proposalCalls); - - // Tiebreaker subcommittee 0 - members = _tiebreakerSubCommittees[0].getMembers(); - for (uint256 i = 0; i < _tiebreakerSubCommittees[0].getQuorum() - 1; i++) { - vm.prank(members[i]); - _tiebreakerSubCommittees[0].scheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerSubCommittees[0].getScheduleProposalState(proposalIdToExecute); - assertTrue(support < quorum); - assertFalse(isExecuted); - } - - vm.prank(members[members.length - 1]); - _tiebreakerSubCommittees[0].scheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerSubCommittees[0].getScheduleProposalState(proposalIdToExecute); - assertEq(support, quorum); - assertFalse(isExecuted); - - _tiebreakerSubCommittees[0].executeScheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerCoreCommittee.getScheduleProposalState(proposalIdToExecute); - assertTrue(support < quorum); - - // Tiebreaker subcommittee 1 - members = _tiebreakerSubCommittees[1].getMembers(); - for (uint256 i = 0; i < _tiebreakerSubCommittees[1].getQuorum() - 1; i++) { - vm.prank(members[i]); - _tiebreakerSubCommittees[1].scheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerSubCommittees[1].getScheduleProposalState(proposalIdToExecute); - assertTrue(support < quorum); - assertEq(isExecuted, false); - } - - vm.prank(members[members.length - 1]); - _tiebreakerSubCommittees[1].scheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerSubCommittees[1].getScheduleProposalState(proposalIdToExecute); - assertEq(support, quorum); - assertFalse(isExecuted); - - // Approve proposal for scheduling - _tiebreakerSubCommittees[1].executeScheduleProposal(proposalIdToExecute); - (support, quorum,, isExecuted) = _tiebreakerCoreCommittee.getScheduleProposalState(proposalIdToExecute); - assertEq(support, quorum); - - // Waiting for submit delay pass - _wait(_tiebreakerCoreCommittee.getTimelockDuration()); - - _tiebreakerCoreCommittee.executeScheduleProposal(proposalIdToExecute); - } - - function test_resume_withdrawals() external { - uint256 quorum; - uint256 support; - bool isExecuted; - - address[] memory members; - - vm.prank(address(_lido.agent)); - _lido.withdrawalQueue.grantRole( - 0x139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d, address(_lido.agent) - ); - vm.prank(address(_lido.agent)); - _lido.withdrawalQueue.pauseFor(type(uint256).max); - assertEq(_lido.withdrawalQueue.isPaused(), true); - - // Tiebreak activation - _assertNormalState(); - _lockStETH(_VETOER, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT()); - _lockStETH(_VETOER, 1 gwei); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); - _activateNextState(); - _assertRageQuitState(); - _wait(_dualGovernance.getTiebreakerDetails().tiebreakerActivationTimeout); - _activateNextState(); - - // Tiebreaker subcommittee 0 - members = _tiebreakerSubCommittees[0].getMembers(); - for (uint256 i = 0; i < _tiebreakerSubCommittees[0].getQuorum() - 1; i++) { - vm.prank(members[i]); - _tiebreakerSubCommittees[0].sealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = - _tiebreakerSubCommittees[0].getSealableResumeState(address(_lido.withdrawalQueue)); - assertTrue(support < quorum); - assertFalse(isExecuted); - } - - vm.prank(members[members.length - 1]); - _tiebreakerSubCommittees[0].sealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = - _tiebreakerSubCommittees[0].getSealableResumeState(address(_lido.withdrawalQueue)); - assertEq(support, quorum); - assertFalse(isExecuted); - - _tiebreakerSubCommittees[0].executeSealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = _tiebreakerCoreCommittee.getSealableResumeState( - address(_lido.withdrawalQueue), - _tiebreakerCoreCommittee.getSealableResumeNonce(address(_lido.withdrawalQueue)) - ); - assertTrue(support < quorum); - - // Tiebreaker subcommittee 1 - members = _tiebreakerSubCommittees[1].getMembers(); - for (uint256 i = 0; i < _tiebreakerSubCommittees[1].getQuorum() - 1; i++) { - vm.prank(members[i]); - _tiebreakerSubCommittees[1].sealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = - _tiebreakerSubCommittees[1].getSealableResumeState(address(_lido.withdrawalQueue)); - assertTrue(support < quorum); - assertEq(isExecuted, false); - } - - vm.prank(members[members.length - 1]); - _tiebreakerSubCommittees[1].sealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = - _tiebreakerSubCommittees[1].getSealableResumeState(address(_lido.withdrawalQueue)); - assertEq(support, quorum); - assertFalse(isExecuted); - - _tiebreakerSubCommittees[1].executeSealableResume(address(_lido.withdrawalQueue)); - (support, quorum,, isExecuted) = _tiebreakerCoreCommittee.getSealableResumeState( - address(_lido.withdrawalQueue), - _tiebreakerCoreCommittee.getSealableResumeNonce(address(_lido.withdrawalQueue)) - ); - assertEq(support, quorum); - - // Waiting for submit delay pass - _wait(_tiebreakerCoreCommittee.getTimelockDuration()); - - _tiebreakerCoreCommittee.executeSealableResume(address(_lido.withdrawalQueue)); - - assertEq(_lido.withdrawalQueue.isPaused(), false); - } -} diff --git a/test/scenario/timelocked-governance.t.sol b/test/scenario/timelocked-governance.t.sol index c822e75f..16d6a3c4 100644 --- a/test/scenario/timelocked-governance.t.sol +++ b/test/scenario/timelocked-governance.t.sol @@ -8,94 +8,48 @@ import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtec import {ExternalCall} from "contracts/libraries/ExecutableProposals.sol"; import {EmergencyProtection} from "contracts/libraries/EmergencyProtection.sol"; -import {ScenarioTestBlueprint, ExternalCallHelpers} from "../utils/scenario-test-blueprint.sol"; +import {ResealManager} from "contracts/ResealManager.sol"; +import {DualGovernance} from "contracts/DualGovernance.sol"; +import {ImmutableDualGovernanceConfigProvider} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; + +import { + ContractsDeployment, + TGScenarioTestSetup, + DGScenarioTestSetup, + ExternalCall, + ExternalCallHelpers +} from "../utils/integration-tests.sol"; import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; -contract TimelockedGovernanceScenario is ScenarioTestBlueprint { +contract TimelockedGovernanceScenario is TGScenarioTestSetup, DGScenarioTestSetup { function setUp() external { - _deployTimelockedGovernanceSetup({isEmergencyProtectionEnabled: true}); + _deployTGSetup({isEmergencyProtectionEnabled: true}); } - function test_operatesAsDefault() external { - // --- - // Act 1. DAO operates as usually. Emergency protection is enabled. - // --- + function testFork_ProtectionAgainstCapture_CancelAllPendingProposals() external { + _step("1. DAO operates as usually. Emergency protection is enabled"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } - // --- - // Act 2. Timeskip. Emergency protection is about to be expired. - // --- - IEmergencyProtectedTimelock.EmergencyProtectionDetails memory emergencyState = - _timelock.getEmergencyProtectionDetails(); - { - assertEq(_timelock.isEmergencyProtectionEnabled(), true); - Duration emergencyProtectionDuration = - Durations.from(emergencyState.emergencyProtectionEndsAfter.toSeconds() - block.timestamp); - _wait(emergencyProtectionDuration.plusSeconds(1)); - assertEq(_timelock.isEmergencyProtectionEnabled(), false); - } - - // --- - // Act 3. Emergency committee has no more power to stop proposal flow. - // - { - vm.prank(address(_timelock.getEmergencyActivationCommittee())); - - vm.expectRevert( - abi.encodeWithSelector( - EmergencyProtection.EmergencyProtectionExpired.selector, - emergencyState.emergencyProtectionEndsAfter.toSeconds() - ) - ); - _timelock.activateEmergencyMode(); - - assertFalse(_timelock.isEmergencyModeActive()); - assertFalse(_timelock.isEmergencyProtectionEnabled()); - } - - // --- - // Act 4. DAO operates as usually. Emergency protection is disabled. - // - { - _daoRegularOperations(_timelockedGovernance); - } - } - - function test_protectionAgainstCapture_cancelProposal() external { - // --- - // Act 1. DAO operates as usually. Emergency protection is enabled. - // --- - { - _daoRegularOperations(_timelockedGovernance); - } - - // --- - // Act 2. Someone creates a malicious proposal. - // --- + _step("2. Malicious proposal is submitted"); (uint256 maliciousProposalId,) = _submitAndAssertMaliciousProposal(); { - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, false); + _wait(_getAfterSubmitDelay().dividedBy(2)); + _assertCanSchedule(maliciousProposalId, false); } - // --- - // Act 3. Emergency committee activates emergency mode. - // --- + _step("3. Emergency mode is activate"); { - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - assertTrue(_timelock.isEmergencyModeActive()); + _activateEmergencyMode(); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, true); - _scheduleProposalViaTimelockedGovernance(maliciousProposalId); + _assertCanSchedule(maliciousProposalId, true); + _scheduleProposal(maliciousProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(maliciousProposalId, false); @@ -103,26 +57,24 @@ contract TimelockedGovernanceScenario is ScenarioTestBlueprint { _executeProposal(maliciousProposalId); } - // --- - // Act 4. DAO decides to cancel all pending proposals and deactivate emergency mode. - // --- + _step("4. DAO decides to cancel all pending proposals and deactivate emergency mode"); { ExternalCall[] memory deactivateEmergencyModeCall = ExternalCallHelpers.create( [address(_timelock)], [abi.encodeCall(_timelock.deactivateEmergencyMode, ())] ); uint256 deactivateEmergencyModeProposalId = - _submitProposal(_timelockedGovernance, "DAO deactivates emergency mode", deactivateEmergencyModeCall); + _submitProposal(deactivateEmergencyModeCall, "DAO deactivates emergency mode"); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaTimelockedGovernance(deactivateEmergencyModeProposalId, true); - _scheduleProposalViaTimelockedGovernance(deactivateEmergencyModeProposalId); + _assertCanSchedule(deactivateEmergencyModeProposalId, true); + _scheduleProposal(deactivateEmergencyModeProposalId); _assertProposalScheduled(deactivateEmergencyModeProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(deactivateEmergencyModeProposalId, false); - _executeEmergencyExecute(deactivateEmergencyModeProposalId); + _emergencyExecute(deactivateEmergencyModeProposalId); assertFalse(_timelock.isEmergencyModeActive()); assertFalse(_timelock.isEmergencyProtectionEnabled()); @@ -131,46 +83,35 @@ contract TimelockedGovernanceScenario is ScenarioTestBlueprint { _assertProposalCancelled(maliciousProposalId); } - // --- - // Act 4. DAO operates as usually. Emergency protection is disabled. - // + _step("5. DAO decides to cancel all pending proposals and deactivate emergency mode"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } } - function test_protectionAgainstCapture_stakersQuit() external { - // --- - // Act 1. DAO operates as usually. Emergency protection is enabled. - // --- + function testFork_ProtectionAgainstCapture_StakersExodus() external { + _step("1. DAO operates as usually. Emergency protection is enabled"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } - // --- - // Act 2. Someone creates a malicious proposal. - // --- + _step("2. Malicious proposal is submitted"); (uint256 maliciousProposalId,) = _submitAndAssertMaliciousProposal(); { - _wait(_timelock.getAfterSubmitDelay().dividedBy(2)); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, false); + _wait(_getAfterSubmitDelay().dividedBy(2)); + _assertCanSchedule(maliciousProposalId, false); } - // --- - // Act 3. Emergency committee activates emergency mode. - // --- + _step("3. Emergency committee activates emergency mode"); { - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); + _activateEmergencyMode(); - assertTrue(_timelock.isEmergencyModeActive()); + _wait(_getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); - _wait(_timelock.getAfterSubmitDelay().dividedBy(2).plusSeconds(1)); + _assertCanSchedule(maliciousProposalId, true); + _scheduleProposal(maliciousProposalId); - _assertCanScheduleViaTimelockedGovernance(maliciousProposalId, true); - _scheduleProposalViaTimelockedGovernance(maliciousProposalId); - - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(maliciousProposalId, false); @@ -178,163 +119,129 @@ contract TimelockedGovernanceScenario is ScenarioTestBlueprint { _executeProposal(maliciousProposalId); } - // --- - // Act 4. DAO decides to not deactivate emergency mode and allow stakers to quit. - // --- + _step("4. DAO decides to not deactivate emergency mode and allow stakers to quit"); { IEmergencyProtectedTimelock.EmergencyProtectionDetails memory emergencyState = _timelock.getEmergencyProtectionDetails(); - assertTrue(_timelock.isEmergencyModeActive()); + assertTrue(_isEmergencyModeActive()); + + vm.warp(_getEmergencyModeEndsAfter().toSeconds() + 1); - _wait( - Durations.from(emergencyState.emergencyModeEndsAfter.toSeconds()).minusSeconds(block.timestamp) - .plusSeconds(2) - ); _timelock.deactivateEmergencyMode(); - assertFalse(_timelock.isEmergencyModeActive()); + assertFalse(_isEmergencyModeActive()); } - // --- - // Act 5. DAO operates as usually. Emergency protection is disabled. - // + _step("5. DAO operates as usually. Emergency protection is disabled"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } } - function test_timelockedGovernance_upgradeTo_dualGovernance_andBack() external { - // --- - // Act 1. DAO operates as usually. Emergency protection is enabled. - // --- + function testFork_TimelockedGovernanceUpgradeToDualGovernanceAndEmergencyReset() external { + _step("1. DAO operates as usually. Emergency protection is enabled"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } - // --- - // Act 2. DAO decides to upgrade system to dual governance. - // --- + _step("2. DAO decides to upgrade system to dual governance"); { - _resealManager = _deployResealManager(_timelock); - _dualGovernanceConfigProvider = _deployDualGovernanceConfigProvider(); - _dualGovernance = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider - }); + _setDGDeployConfig(_getDefaultDGDeployConfig({emergencyGovernanceProposer: address(_lido.voting)})); + _dgDeployedContracts.resealManager = ContractsDeployment.deployResealManager(_timelock); + _dgDeployedContracts.dualGovernanceConfigProvider = + ContractsDeployment.deployDualGovernanceConfigProvider(_dgDeployConfig.dualGovernanceConfigProvider); + _dgDeployedContracts.dualGovernance = ContractsDeployment.deployDualGovernance( + DualGovernance.DualGovernanceComponents({ + timelock: _timelock, + resealManager: _dgDeployedContracts.resealManager, + configProvider: _dgDeployedContracts.dualGovernanceConfigProvider + }), + _dgDeployConfig.dualGovernance.signallingTokens, + _dgDeployConfig.dualGovernance.sanityCheckParams + ); ExternalCall[] memory dualGovernanceLaunchCalls = ExternalCallHelpers.create( - [address(_dualGovernance), address(_timelock)], + [address(_dgDeployedContracts.dualGovernance), address(_timelock)], [ - abi.encodeCall(_dualGovernance.registerProposer, (address(_lido.voting), _timelock.getAdminExecutor())), - abi.encodeCall(_timelock.setGovernance, (address(_dualGovernance))) + abi.encodeCall( + _dgDeployedContracts.dualGovernance.registerProposer, + (address(_lido.voting), _timelock.getAdminExecutor()) + ), + abi.encodeCall(_timelock.setGovernance, (address(_dgDeployedContracts.dualGovernance))) ] ); uint256 dualGovernanceLunchProposalId = - _submitProposal(_timelockedGovernance, "Launch the Dual Governance", dualGovernanceLaunchCalls); + _submitProposal(dualGovernanceLaunchCalls, "Launch the Dual Governance"); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaTimelockedGovernance(dualGovernanceLunchProposalId, true); - _scheduleProposalViaTimelockedGovernance(dualGovernanceLunchProposalId); + _assertCanSchedule(dualGovernanceLunchProposalId, true); + _scheduleProposal(dualGovernanceLunchProposalId); _assertProposalScheduled(dualGovernanceLunchProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _executeProposal(dualGovernanceLunchProposalId); - assertEq(_timelock.getGovernance(), address(_dualGovernance)); + assertEq(_timelock.getGovernance(), address(_dgDeployedContracts.dualGovernance)); } - // --- - // Act 3. DAO operates as usually. Emergency protection is enabled. - // --- + _step("3. DAO operates as usually. Emergency protection is enabled"); { - _daoRegularOperations(_dualGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } - // --- - // Act 4. Someone finds a bug in dual governance. Emergency committee decides to activate emergency mode and DAO decides to downgrade system to single governance. - // --- + _step( + string.concat( + "4. Someone finds a bug in dual governance. Emergency committee decides to activate", + "emergency mode and DAO decides to downgrade system to single governance" + ) + ); { - vm.prank(address(_emergencyActivationCommittee)); - _timelock.activateEmergencyMode(); - - assertTrue(_timelock.isEmergencyModeActive()); + _activateEmergencyMode(); ExternalCall[] memory timelockedGovernanceLaunchCalls = ExternalCallHelpers.create( address(_timelock), [ - abi.encodeCall(_timelock.setGovernance, (address(_timelockedGovernance))), + abi.encodeCall(_timelock.setGovernance, (address(_tgDeployedContracts.timelockedGovernance))), abi.encodeCall(_timelock.deactivateEmergencyMode, ()) ] ); uint256 timelockedGovernanceLunchProposalId = - _submitProposal(_dualGovernance, "Launch the Timelocked Governance", timelockedGovernanceLaunchCalls); + _submitProposalByAdminProposer(timelockedGovernanceLaunchCalls, "Launch the Timelocked Governance"); - _waitAfterSubmitDelayPassed(); + _wait(_getAfterSubmitDelay()); - _assertCanScheduleViaDualGovernance(timelockedGovernanceLunchProposalId, true); - _scheduleProposalViaDualGovernance(timelockedGovernanceLunchProposalId); + _assertCanSchedule(timelockedGovernanceLunchProposalId, true); + _scheduleProposal(timelockedGovernanceLunchProposalId); - _waitAfterScheduleDelayPassed(); + _wait(_getAfterScheduleDelay()); _assertCanExecute(timelockedGovernanceLunchProposalId, false); - _executeEmergencyExecute(timelockedGovernanceLunchProposalId); + _emergencyExecute(timelockedGovernanceLunchProposalId); - assertEq(_timelock.getGovernance(), address(_timelockedGovernance)); + assertEq(_timelock.getGovernance(), address(_tgDeployedContracts.timelockedGovernance)); } - // --- - // Act 5. DAO operates as usually. Emergency protection is enabled. - // --- + _step("5. DAO operates as usually. Emergency protection is enabled"); { - _daoRegularOperations(_timelockedGovernance); + _adoptProposal(_getMockTargetRegularStaffCalls({callsCount: 5}), "Regular staff calls"); } } - function _submitAndAssertProposal(IGovernance governance) internal returns (uint256, ExternalCall[] memory) { - ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); - uint256 proposalId = - _submitProposal(governance, "DAO does regular staff on potentially dangerous contract", regularStaffCalls); - - _assertProposalSubmitted(proposalId); - _assertSubmittedProposalData(proposalId, regularStaffCalls); - - return (proposalId, regularStaffCalls); - } - function _submitAndAssertMaliciousProposal() internal returns (uint256, ExternalCall[] memory) { ExternalCall[] memory maliciousCalls = ExternalCallHelpers.create( address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doRugPool, ()) ); - uint256 proposalId = _submitProposal( - _timelockedGovernance, "DAO does malicious staff on potentially dangerous contract", maliciousCalls - ); + uint256 proposalId = + _submitProposal(maliciousCalls, "DAO does malicious staff on potentially dangerous contract"); _assertProposalSubmitted(proposalId); _assertSubmittedProposalData(proposalId, maliciousCalls); return (proposalId, maliciousCalls); } - - function _daoRegularOperations(IGovernance governance) internal { - (uint256 proposalId, ExternalCall[] memory regularStaffCalls) = _submitAndAssertProposal(governance); - - _waitAfterSubmitDelayPassed(); - - _assertCanSchedule(governance, proposalId, true); - _scheduleProposal(governance, proposalId); - _assertProposalScheduled(proposalId); - - _waitAfterScheduleDelayPassed(); - - _assertCanExecute(proposalId, true); - _executeProposal(proposalId); - - _assertTargetMockCalls(_timelock.getAdminExecutor(), regularStaffCalls); - } } diff --git a/test/scenario/veto-cooldown-mechanics.t.sol b/test/scenario/veto-cooldown-mechanics.t.sol index 8964f61d..9f2f47a6 100644 --- a/test/scenario/veto-cooldown-mechanics.t.sol +++ b/test/scenario/veto-cooldown-mechanics.t.sol @@ -1,75 +1,71 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; +import { + Escrow, + DGScenarioTestSetup, + ExternalCallHelpers, + ExternalCall, + IPotentiallyDangerousContract, + IRageQuitEscrow +} from "../utils/integration-tests.sol"; + import {PercentsD16} from "contracts/types/PercentD16.sol"; import {DualGovernance} from "contracts/DualGovernance.sol"; -import {IPotentiallyDangerousContract} from "../utils/interfaces/IPotentiallyDangerousContract.sol"; - -import {LidoUtils} from "../utils/lido-utils.sol"; -import {Escrow, ExternalCall, ExternalCallHelpers, ScenarioTestBlueprint} from "../utils/scenario-test-blueprint.sol"; - -contract VetoCooldownMechanicsTest is ScenarioTestBlueprint { - using LidoUtils for LidoUtils.Context; - +contract VetoCooldownMechanicsTest is DGScenarioTestSetup { function setUp() external { - _deployDualGovernanceSetup({isEmergencyProtectionEnabled: false}); + _deployDGSetup({isEmergencyProtectionEnabled: false}); } function testFork_ProposalSubmittedInRageQuitNonExecutableInTheNextVetoCooldown() external { ExternalCall[] memory regularStaffCalls = _getMockTargetRegularStaffCalls(); uint256 proposalId; - _step("1. THE PROPOSAL IS SUBMITTED"); + _step("1. The proposal is submitted"); { - proposalId = _submitProposal( - _dualGovernance, "Propose to doSmth on target passing dual governance", regularStaffCalls - ); + proposalId = + _submitProposalByAdminProposer(regularStaffCalls, "Propose to doSmth on target passing dual governance"); _assertSubmittedProposalData(proposalId, _timelock.getAdminExecutor(), regularStaffCalls); - _assertCanSchedule(_dualGovernance, proposalId, false); + _assertCanSchedule(proposalId, false); } address vetoer = makeAddr("MALICIOUS_ACTOR"); - _setupStETHBalance( - vetoer, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1_00) - ); - _step("2. THE SECOND SEAL RAGE QUIT SUPPORT IS ACQUIRED"); + _setupStETHBalance(vetoer, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1_00)); + _step("2. The second seal rage quit support is acquired"); { - _lockStETH( - vetoer, _dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT() + PercentsD16.fromBasisPoints(1) - ); + _lockStETH(vetoer, _getSecondSealRageQuitSupport() + PercentsD16.fromBasisPoints(1)); _assertVetoSignalingState(); - _wait(_dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION().plusSeconds(1)); + _wait(_getVetoSignallingMaxDuration().plusSeconds(1)); _activateNextState(); _assertRageQuitState(); } uint256 anotherProposalId; - _step("3. ANOTHER PROPOSAL IS SUBMITTED DURING THE RAGE QUIT STATE"); + _step("3. Another proposal is submitted during the rage quit state"); { _activateNextState(); _assertRageQuitState(); - anotherProposalId = _submitProposal( - _dualGovernance, - "Another Proposal", + anotherProposalId = _submitProposalByAdminProposer( ExternalCallHelpers.create( address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doRugPool, ()) - ) + ), + "Another Proposal" ); } - _step("4. RAGE QUIT IS FINALIZED"); + _step("4. Rage quit is finalized"); { // request withdrawals batches - Escrow rageQuitEscrow = _getRageQuitEscrow(); + IRageQuitEscrow rageQuitEscrow = _getRageQuitEscrow(); while (!rageQuitEscrow.isWithdrawalsBatchesClosed()) { rageQuitEscrow.requestNextWithdrawalsBatch(96); } - _lido.finalizeWithdrawalQueue(); + _finalizeWithdrawalQueue(); while (rageQuitEscrow.getUnclaimedUnstETHIdsCount() > 0) { rageQuitEscrow.claimNextWithdrawalsBatch(128); @@ -77,20 +73,20 @@ contract VetoCooldownMechanicsTest is ScenarioTestBlueprint { rageQuitEscrow.startRageQuitExtensionPeriod(); - _wait(_dualGovernanceConfigProvider.RAGE_QUIT_EXTENSION_PERIOD_DURATION().plusSeconds(1)); + _wait(_getRageQuitExtensionPeriodDuration().plusSeconds(1)); assertTrue(rageQuitEscrow.isRageQuitFinalized()); } - _step("5. PROPOSAL SUBMITTED BEFORE RAGE QUIT IS EXECUTABLE"); + _step("5. Proposal submitted before rage quit is executable"); { _activateNextState(); _assertVetoCooldownState(); - this.scheduleProposalExternal(proposalId); + this.external__scheduleProposal(proposalId); _assertProposalScheduled(proposalId); } - _step("6. PROPOSAL SUBMITTED DURING RAGE QUIT IS NOT EXECUTABLE"); + _step("6. Proposal submitted during rage quit is not executable"); { _activateNextState(); _assertVetoCooldownState(); @@ -98,11 +94,7 @@ contract VetoCooldownMechanicsTest is ScenarioTestBlueprint { vm.expectRevert( abi.encodeWithSelector(DualGovernance.ProposalSchedulingBlocked.selector, anotherProposalId) ); - this.scheduleProposalExternal(anotherProposalId); + this.external__scheduleProposal(anotherProposalId); } } - - function scheduleProposalExternal(uint256 proposalId) external { - _scheduleProposal(_dualGovernance, proposalId); - } } diff --git a/test/unit/Escrow.t.sol b/test/unit/Escrow.t.sol index b292d95b..4a16ea36 100644 --- a/test/unit/Escrow.t.sol +++ b/test/unit/Escrow.t.sol @@ -3,9 +3,11 @@ pragma solidity 0.8.26; import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// solhint-disable-next-line no-console +import {console} from "forge-std/console.sol"; import {Duration, Durations} from "contracts/types/Duration.sol"; -import {Timestamp, Timestamps} from "contracts/types/Timestamp.sol"; +import {Timestamps} from "contracts/types/Timestamp.sol"; import {ETHValues} from "contracts/types/ETHValue.sol"; import {SharesValues} from "contracts/types/SharesValue.sol"; import {PercentD16, PercentsD16} from "contracts/types/PercentD16.sol"; @@ -29,6 +31,10 @@ import {WithdrawalQueueMock} from "test/mocks/WithdrawalQueueMock.sol"; import {UnitTest} from "test/utils/unit-test.sol"; import {Random} from "test/utils/random.sol"; +uint256 constant ACCURACY = 2 wei; +uint256 constant ONE_PERCENT_D16 = 10 ** 16; +uint256 constant TWENTY_PERCENTS_D16 = 20 * ONE_PERCENT_D16; + interface IEscrow is ISignallingEscrow, IRageQuitEscrow {} contract EscrowUnitTests is UnitTest { @@ -47,9 +53,15 @@ contract EscrowUnitTests is UnitTest { Duration private _minLockAssetDuration = Durations.from(1 days); Duration private _maxMinAssetsLockDuration = Durations.from(100 days); uint256 private stethAmount = 100 ether; + uint256 private stethInitialEthAmount = 100 wei + stethAmount; function setUp() external { - _random = Random.create(block.timestamp); + uint256 randomSeed = vm.unixTime(); + _random = Random.create(randomSeed); + + // solhint-disable-next-line no-console + console.log("Using random seed:", randomSeed); + _stETH = new StETHMock(); _wstETH = new WstETHMock(_stETH); _withdrawalQueue = new WithdrawalQueueMock(_stETH); @@ -68,7 +80,6 @@ contract EscrowUnitTests is UnitTest { vm.stopPrank(); _stETH.mint(_vetoer, stethAmount); - _wstETH.mint(_vetoer, stethAmount); vm.mockCall( _dualGovernance, abi.encodeWithSelector(IDualGovernance.activateNextState.selector), abi.encode(true) @@ -76,14 +87,21 @@ contract EscrowUnitTests is UnitTest { _withdrawalQueue.setMinStETHWithdrawalAmount(100); _withdrawalQueue.setMaxStETHWithdrawalAmount(1000 * 1e18); + uint256 variablePercent = Random.nextUint256(_random, TWENTY_PERCENTS_D16); + uint256 rebaseFactor = 90 * ONE_PERCENT_D16 + variablePercent; + PercentD16 rebaseFactorD16 = PercentsD16.from(rebaseFactor); + + // solhint-disable-next-line no-console + console.log("Using ST_ETH rebase factor (%%):", _percentD16ToString(rebaseFactorD16)); + + _stETH.rebaseTotalPooledEther(rebaseFactorD16); + vm.label(address(_escrow), "Escrow"); vm.label(address(_stETH), "StETHMock"); vm.label(address(_wstETH), "WstETHMock"); vm.label(address(_withdrawalQueue), "WithdrawalQueueMock"); } - /* */ - // --- // constructor() // --- @@ -126,9 +144,18 @@ contract EscrowUnitTests is UnitTest { vm.expectCall(address(_stETH), abi.encodeCall(IERC20.approve, (address(_wstETH), type(uint256).max))); vm.expectCall(address(_stETH), abi.encodeCall(IERC20.approve, (address(_withdrawalQueue), type(uint256).max))); - _createInitializedEscrowProxy({minWithdrawalsBatchSize: 100, minAssetsLockDuration: Durations.ZERO}); + Escrow escrowInstance = + _createInitializedEscrowProxy({minWithdrawalsBatchSize: 100, minAssetsLockDuration: Durations.ZERO}); - assertEq(_escrow.MIN_WITHDRAWALS_BATCH_SIZE(), 100); + assertEq(escrowInstance.MIN_WITHDRAWALS_BATCH_SIZE(), 100); + assertEq(escrowInstance.getMinAssetsLockDuration(), Durations.ZERO); + assertTrue(escrowInstance.getEscrowState() == EscrowState.SignallingEscrow); + + IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = escrowInstance.getSignallingEscrowDetails(); + assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); } function test_initialize_RevertOn_CalledNotViaProxy() external { @@ -164,28 +191,37 @@ contract EscrowUnitTests is UnitTest { // --- function test_lockStETH_HappyPath() external { - uint256 amount = 1 ether; - - uint256 sharesAmount = _stETH.getSharesByPooledEth(amount); + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); uint256 vetoerBalanceBefore = _stETH.balanceOf(_vetoer); uint256 escrowBalanceBefore = _stETH.balanceOf(address(_escrow)); vm.expectCall( address(_stETH), - abi.encodeCall(IStETH.transferSharesFrom, (address(_vetoer), address(_escrow), sharesAmount)) + abi.encodeCall( + IStETH.transferSharesFrom, (address(_vetoer), address(_escrow), _stETH.getSharesByPooledEth(amount)) + ) ); vm.expectCall(address(_dualGovernance), abi.encodeCall(IDualGovernance.activateNextState, ()), 2); vm.prank(_vetoer); uint256 lockedStETHShares = _escrow.lockStETH(amount); - assertEq(lockedStETHShares, sharesAmount); + assertApproxEqAbs(lockedStETHShares, sharesAmount, ACCURACY); uint256 vetoerBalanceAfter = _stETH.balanceOf(_vetoer); uint256 escrowBalanceAfter = _stETH.balanceOf(address(_escrow)); - assertEq(vetoerBalanceAfter, vetoerBalanceBefore - amount); - assertEq(escrowBalanceAfter, escrowBalanceBefore + amount); + assertApproxEqAbs( + vetoerBalanceAfter, + _stETH.getPooledEthByShares(_stETH.getSharesByPooledEth(vetoerBalanceBefore) - sharesAmount), + 2 * ACCURACY + ); + assertApproxEqAbs( + escrowBalanceAfter, + _stETH.getPooledEthByShares(_stETH.getSharesByPooledEth(escrowBalanceBefore) + sharesAmount), + 2 * ACCURACY + ); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); @@ -219,27 +255,33 @@ contract EscrowUnitTests is UnitTest { // --- function test_unlockStETH_HappyPath() external { - uint256 amount = 1 ether; - uint256 sharesAmount = _stETH.getSharesByPooledEth(amount); + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); vm.startPrank(_vetoer); _escrow.lockStETH(amount); uint256 vetoerBalanceBefore = _stETH.balanceOf(_vetoer); - uint256 escrowBalanceBefore = _stETH.balanceOf(address(_escrow)); _wait(_minLockAssetDuration.plusSeconds(1)); - vm.expectCall(address(_stETH), abi.encodeCall(IStETH.transferShares, (address(_vetoer), sharesAmount))); + vm.expectCall( + address(_stETH), + abi.encodeCall(IStETH.transferShares, (address(_vetoer), _stETH.getSharesByPooledEth(amount))) + ); vm.expectCall(address(_dualGovernance), abi.encodeCall(IDualGovernance.activateNextState, ()), 2); uint256 unlockedStETHShares = _escrow.unlockStETH(); - assertEq(unlockedStETHShares, sharesAmount); + assertApproxEqAbs(unlockedStETHShares, sharesAmount, ACCURACY); uint256 vetoerBalanceAfter = _stETH.balanceOf(_vetoer); uint256 escrowBalanceAfter = _stETH.balanceOf(address(_escrow)); - assertEq(vetoerBalanceAfter, vetoerBalanceBefore + amount); - assertEq(escrowBalanceAfter, escrowBalanceBefore - amount); + assertApproxEqAbs( + vetoerBalanceAfter, + _stETH.getPooledEthByShares(_stETH.getSharesByPooledEth(vetoerBalanceBefore) + sharesAmount), + ACCURACY + ); + assertEq(escrowBalanceAfter, 0); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); @@ -256,8 +298,9 @@ contract EscrowUnitTests is UnitTest { } function test_unlockStETH_RevertOn_UnexpectedEscrowState() external { + uint256 amount = _stETH.getPooledEthByShares(1 ether); vm.prank(_vetoer); - _escrow.lockStETH(1 ether); + _escrow.lockStETH(amount); _transitToRageQuit(); @@ -270,7 +313,7 @@ contract EscrowUnitTests is UnitTest { function test_unlockStETH_RevertOn_MinAssetsLockDurationNotPassed() external { vm.startPrank(_vetoer); - _escrow.lockStETH(1 ether); + _escrow.lockStETH(_stETH.getPooledEthByShares(1 ether)); uint256 lastLockTimestamp = block.timestamp; @@ -290,25 +333,28 @@ contract EscrowUnitTests is UnitTest { // --- function test_lockWstETH_HappyPath() external { - uint256 amount = 1 ether; + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); vm.startPrank(_vetoer); - _wstETH.wrap(amount); + uint256 wstEthAmount = _wstETH.wrap(amount); + assertApproxEqAbs(wstEthAmount, sharesAmount, ACCURACY); uint256 vetoerWStBalanceBefore = _wstETH.balanceOf(_vetoer); uint256 escrowBalanceBefore = _stETH.balanceOf(address(_escrow)); + assertEq(escrowBalanceBefore, 0); - vm.expectCall(address(_wstETH), abi.encodeCall(IERC20.transferFrom, (_vetoer, address(_escrow), amount))); + vm.expectCall(address(_wstETH), abi.encodeCall(IERC20.transferFrom, (_vetoer, address(_escrow), wstEthAmount))); vm.expectCall(address(_dualGovernance), abi.encodeCall(IDualGovernance.activateNextState, ()), 2); - uint256 lockedStETHShares = _escrow.lockWstETH(amount); - assertEq(lockedStETHShares, _stETH.getSharesByPooledEth(amount)); + uint256 lockedStETHShares = _escrow.lockWstETH(wstEthAmount); + assertApproxEqAbs(lockedStETHShares, _stETH.getSharesByPooledEth(amount), ACCURACY); uint256 vetoerWStBalanceAfter = _wstETH.balanceOf(_vetoer); uint256 escrowBalanceAfter = _stETH.balanceOf(address(_escrow)); - assertEq(vetoerWStBalanceAfter, vetoerWStBalanceBefore - lockedStETHShares); - assertEq(escrowBalanceAfter, escrowBalanceBefore + lockedStETHShares); + assertApproxEqAbs(vetoerWStBalanceAfter, vetoerWStBalanceBefore - lockedStETHShares, ACCURACY); + assertApproxEqAbs(escrowBalanceAfter, _stETH.getPooledEthByShares(lockedStETHShares), ACCURACY); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); @@ -340,30 +386,37 @@ contract EscrowUnitTests is UnitTest { // --- function test_unlockWstETH_HappyPath() external { - uint256 amount = 1 ether; + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); vm.startPrank(_vetoer); - _wstETH.wrap(amount); + uint256 wstEthAmount = _wstETH.wrap(amount); + assertApproxEqAbs(wstEthAmount, sharesAmount, ACCURACY); - _escrow.lockWstETH(amount); + uint256 lockedStETHShares = _escrow.lockWstETH(wstEthAmount); + assertApproxEqAbs(lockedStETHShares, _stETH.getSharesByPooledEth(amount), ACCURACY); _wait(_minLockAssetDuration.plusSeconds(1)); uint256 vetoerWStBalanceBefore = _wstETH.balanceOf(_vetoer); uint256 escrowBalanceBefore = _stETH.balanceOf(address(_escrow)); - vm.expectCall(address(_wstETH), abi.encodeCall(IWstETH.wrap, (amount))); - vm.expectCall(address(_wstETH), abi.encodeCall(IERC20.transfer, (_vetoer, amount))); + vm.expectCall(address(_wstETH), abi.encodeCall(IWstETH.wrap, (escrowBalanceBefore))); + vm.expectCall( + address(_wstETH), + abi.encodeCall(IERC20.transfer, (_vetoer, _stETH.getSharesByPooledEth(escrowBalanceBefore))) + ); vm.expectCall(address(_dualGovernance), abi.encodeCall(IDualGovernance.activateNextState, ()), 2); uint256 unlockedStETHShares = _escrow.unlockWstETH(); - assertEq(unlockedStETHShares, _stETH.getPooledEthByShares(amount)); + assertApproxEqAbs(unlockedStETHShares, wstEthAmount, 2 * ACCURACY); uint256 vetoerWStBalanceAfter = _wstETH.balanceOf(_vetoer); uint256 escrowBalanceAfter = _stETH.balanceOf(address(_escrow)); assertEq(vetoerWStBalanceAfter, vetoerWStBalanceBefore + unlockedStETHShares); - assertEq(escrowBalanceAfter, escrowBalanceBefore - unlockedStETHShares); + assertApproxEqAbs(vetoerWStBalanceAfter, wstEthAmount, 2 * ACCURACY); + assertApproxEqAbs(escrowBalanceAfter, 0, ACCURACY); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); @@ -380,11 +433,12 @@ contract EscrowUnitTests is UnitTest { } function test_unlockWstETH_RevertOn_UnexpectedEscrowState() external { - uint256 amount = 1 ether; + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); vm.startPrank(_vetoer); - _wstETH.wrap(amount); - _escrow.lockWstETH(amount); + uint256 wstEthAmount = _wstETH.wrap(amount); + _escrow.lockWstETH(wstEthAmount); vm.stopPrank(); _transitToRageQuit(); @@ -394,14 +448,18 @@ contract EscrowUnitTests is UnitTest { ); vm.prank(_vetoer); _escrow.unlockWstETH(); + + assertApproxEqAbs(_stETH.balanceOf(address(_escrow)), amount, ACCURACY); + assertEq(_wstETH.balanceOf(_vetoer), 0); } function test_unlockWstETH_RevertOn_MinAssetsLockDurationNotPassed() external { - uint256 amount = 1 ether; + uint256 sharesAmount = 1 ether; + uint256 amount = _stETH.getPooledEthByShares(sharesAmount); vm.startPrank(_vetoer); - _wstETH.wrap(amount); - _escrow.lockWstETH(amount); + uint256 wstEthAmount = _wstETH.wrap(amount); + _escrow.lockWstETH(wstEthAmount); uint256 lastLockTimestamp = block.timestamp; @@ -414,6 +472,9 @@ contract EscrowUnitTests is UnitTest { ) ); _escrow.unlockWstETH(); + + assertApproxEqAbs(_stETH.balanceOf(address(_escrow)), amount, ACCURACY); + assertEq(_wstETH.balanceOf(_vetoer), 0); } // --- @@ -426,8 +487,12 @@ contract EscrowUnitTests is UnitTest { unstethIds[1] = 2; IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = new IWithdrawalQueue.WithdrawalRequestStatus[](2); - statuses[0] = IWithdrawalQueue.WithdrawalRequestStatus(1 ether, 1 ether, _vetoer, block.timestamp, false, false); - statuses[1] = IWithdrawalQueue.WithdrawalRequestStatus(2 ether, 2 ether, _vetoer, block.timestamp, false, false); + statuses[0] = IWithdrawalQueue.WithdrawalRequestStatus( + 1 ether, _stETH.getSharesByPooledEth(1 ether), _vetoer, block.timestamp, false, false + ); + statuses[1] = IWithdrawalQueue.WithdrawalRequestStatus( + 2 ether, _stETH.getSharesByPooledEth(2 ether), _vetoer, block.timestamp, false, false + ); _withdrawalQueue.setWithdrawalRequestsStatuses(statuses); @@ -486,8 +551,8 @@ contract EscrowUnitTests is UnitTest { function test_unlockUnstETH_HappyPath() external { uint256[] memory unstETHAmounts = new uint256[](2); - unstETHAmounts[0] = 1 ether; - unstETHAmounts[1] = 2 ether; + unstETHAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstETHAmounts[1] = _stETH.getPooledEthByShares(2 ether); uint256[] memory unstethIds = _vetoerLockedUnstEth(unstETHAmounts); @@ -561,6 +626,82 @@ contract EscrowUnitTests is UnitTest { // --- function test_markUnstETHFinalized_HappyPath() external { + uint256 unstethShares1 = 30 ether; + uint256 unstethShares2 = 2 ether; + uint256[] memory unstETHAmounts = new uint256[](2); + unstETHAmounts[0] = _stETH.getPooledEthByShares(unstethShares1); + unstETHAmounts[1] = _stETH.getPooledEthByShares(unstethShares2); + uint256[] memory unstethIds = _vetoerLockedUnstEth(unstETHAmounts); + + IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); + + assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), 0); + assertApproxEqAbs( + signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), + unstethShares1 + unstethShares2, + 2 * ACCURACY + ); + assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); + + IEscrow.VetoerDetails memory state = _escrow.getVetoerDetails(_vetoer); + + assertEq(state.unstETHIdsCount, 2); + assertEq(state.stETHLockedShares.toUint256(), 0); + assertApproxEqAbs(state.unstETHLockedShares.toUint256(), unstethShares1 + unstethShares2, 2 * ACCURACY); + assertEq( + _escrow.getRageQuitSupport().toUint256(), + PercentsD16.fromFraction({ + numerator: _stETH.getPooledEthByShares(unstethShares1 + unstethShares2), + denominator: _stETH.totalSupply() + }).toUint256() + ); + + assertTrue(_escrow.getEscrowState() == EscrowState.SignallingEscrow); + + uint256[] memory hints = new uint256[](2); + uint256[] memory responses = new uint256[](2); + + hints[0] = 1; + hints[1] = 1; + + responses[0] = unstETHAmounts[0]; + responses[1] = unstETHAmounts[1]; + + _withdrawalQueue.setClaimableEtherResult(responses); + vm.expectCall( + address(_withdrawalQueue), abi.encodeCall(IWithdrawalQueue.getClaimableEther, (unstethIds, hints)) + ); + + _escrow.markUnstETHFinalized(unstethIds, hints); + + assertTrue(_escrow.getEscrowState() == EscrowState.SignallingEscrow); + + signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); + + assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), unstETHAmounts[0] + unstETHAmounts[1]); + + state = _escrow.getVetoerDetails(_vetoer); + + assertEq(state.unstETHIdsCount, 2); + assertEq(state.stETHLockedShares.toUint256(), 0); + assertApproxEqAbs(state.unstETHLockedShares.toUint256(), unstethShares1 + unstethShares2, 2 * ACCURACY); + + PercentD16 support = _escrow.getRageQuitSupport(); + + assertEq( + support.toUint256(), + PercentsD16.fromFraction({ + numerator: unstETHAmounts[0] + unstETHAmounts[1], + denominator: _stETH.totalSupply() + unstETHAmounts[0] + unstETHAmounts[1] + }).toUint256() + ); + } + + function test_markUnstETHFinalized_HappyPath_NFTs_not_locked_in_Escrow() external { uint256[] memory unstethIds = new uint256[](2); uint256[] memory hints = new uint256[](2); uint256[] memory responses = new uint256[](2); @@ -571,15 +712,28 @@ contract EscrowUnitTests is UnitTest { hints[0] = 1; hints[1] = 1; - responses[0] = 1 ether; - responses[1] = 1 ether; + responses[0] = _stETH.getPooledEthByShares(1 ether); + responses[1] = _stETH.getPooledEthByShares(1 ether); _withdrawalQueue.setClaimableEtherResult(responses); vm.expectCall( address(_withdrawalQueue), abi.encodeCall(IWithdrawalQueue.getClaimableEther, (unstethIds, hints)) ); + assertTrue(_escrow.getEscrowState() == EscrowState.SignallingEscrow); + assertEq(_escrow.getRageQuitSupport().toUint256(), 0); + _escrow.markUnstETHFinalized(unstethIds, hints); + + assertTrue(_escrow.getEscrowState() == EscrowState.SignallingEscrow); + assertEq(_escrow.getRageQuitSupport().toUint256(), 0); + + IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); + + assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); + assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); } function test_markUnstETHFinalized_RevertOn_UnexpectedEscrowState() external { @@ -693,6 +847,7 @@ contract EscrowUnitTests is UnitTest { // --- function test_claimNextWithdrawalsBatch_2_HappyPath() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); @@ -702,35 +857,35 @@ contract EscrowUnitTests is UnitTest { uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); _withdrawalQueue.setLastCheckpointIndex(1); _withdrawalQueue.setCheckpointHints(new uint256[](unstEthIds.length)); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); - _withdrawalQueue.setClaimableAmount(stethAmount); - vm.deal(address(_withdrawalQueue), stethAmount); + _withdrawalQueue.setClaimableAmount(ethAmount); + vm.deal(address(_withdrawalQueue), ethAmount); vm.expectEmit(); emit WithdrawalsBatchesQueue.UnstETHIdsClaimed(unstEthIds); vm.expectEmit(); - emit AssetsAccounting.ETHClaimed(ETHValues.from(stethAmount)); + emit AssetsAccounting.ETHClaimed(ETHValues.from(ethAmount)); _escrow.claimNextWithdrawalsBatch(unstEthIds[0], new uint256[](unstEthIds.length)); signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); - assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), stethAmount); - assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), stethAmount); + assertApproxEqAbs(signallingEscrowDetails.totalStETHLockedShares.toUint256(), stethAmount, ACCURACY); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), ethAmount); assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); IEscrow.VetoerDetails memory state = _escrow.getVetoerDetails(_vetoer); assertEq(state.unstETHIdsCount, 0); - assertEq(state.stETHLockedShares.toUint256(), stethAmount); + assertApproxEqAbs(state.stETHLockedShares.toUint256(), stethAmount, ACCURACY); assertEq(state.unstETHLockedShares.toUint256(), 0); } @@ -759,34 +914,36 @@ contract EscrowUnitTests is UnitTest { } function test_claimNextWithdrawalsBatch_2_RevertOn_InvalidFromUnstETHId() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); - _withdrawalQueue.setClaimableAmount(stethAmount); - vm.deal(address(_withdrawalQueue), stethAmount); + _withdrawalQueue.setClaimableAmount(ethAmount); + vm.deal(address(_withdrawalQueue), ethAmount); vm.expectRevert(abi.encodeWithSelector(Escrow.InvalidFromUnstETHId.selector, unstEthIds[0] + 10)); _escrow.claimNextWithdrawalsBatch(unstEthIds[0] + 10, new uint256[](1)); } function test_claimNextWithdrawalsBatch_2_RevertOn_InvalidHintsLength() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); - _withdrawalQueue.setClaimableAmount(stethAmount); - vm.deal(address(_withdrawalQueue), stethAmount); + _withdrawalQueue.setClaimableAmount(ethAmount); + vm.deal(address(_withdrawalQueue), ethAmount); vm.expectRevert(abi.encodeWithSelector(Escrow.InvalidHintsLength.selector, 10, 1)); _escrow.claimNextWithdrawalsBatch(unstEthIds[0], new uint256[](10)); @@ -797,6 +954,7 @@ contract EscrowUnitTests is UnitTest { // --- function test_claimNextWithdrawalsBatch_1_HappyPath() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); @@ -806,32 +964,32 @@ contract EscrowUnitTests is UnitTest { uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); IEscrow.VetoerDetails memory vetoerState = _escrow.getVetoerDetails(_vetoer); assertEq(vetoerState.unstETHIdsCount, 0); - assertEq(vetoerState.stETHLockedShares.toUint256(), stethAmount); + assertApproxEqAbs(vetoerState.stETHLockedShares.toUint256(), stethAmount, ACCURACY); assertEq(vetoerState.unstETHLockedShares.toUint256(), 0); - _claimStEthViaWQ(unstEthIds, stethAmount); + _claimStEthViaWQ(unstEthIds, ethAmount); signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); - assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), stethAmount); - assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), stethAmount); + assertApproxEqAbs(signallingEscrowDetails.totalStETHLockedShares.toUint256(), stethAmount, ACCURACY); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), ethAmount); assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); vetoerState = _escrow.getVetoerDetails(_vetoer); assertEq(vetoerState.unstETHIdsCount, 0); - assertEq(vetoerState.stETHLockedShares.toUint256(), stethAmount); + assertApproxEqAbs(vetoerState.stETHLockedShares.toUint256(), stethAmount, ACCURACY); assertEq(vetoerState.unstETHLockedShares.toUint256(), 0); } @@ -862,14 +1020,14 @@ contract EscrowUnitTests is UnitTest { function test_claimNextWithdrawalsBatch_1_RevertOn_InvalidHintsLength() external { uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(_stETH.getPooledEthByShares(stethAmount)); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); _withdrawalQueue.setLastCheckpointIndex(1); _withdrawalQueue.setCheckpointHints(new uint256[](unstEthIds.length + 10)); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); vm.expectRevert(abi.encodeWithSelector(Escrow.InvalidHintsLength.selector, 11, 1)); _escrow.claimNextWithdrawalsBatch(unstEthIds.length); @@ -895,27 +1053,28 @@ contract EscrowUnitTests is UnitTest { function test_startRageQuitExtensionPeriod_RevertOn_UnclaimedBatches() external { uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(_stETH.getPooledEthByShares(stethAmount)); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); vm.expectRevert(Escrow.UnclaimedBatches.selector); _escrow.startRageQuitExtensionPeriod(); } function test_startRageQuitExtensionPeriod_RevertOn_UnfinalizedUnstETHIds() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); - _claimStEthViaWQ(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); + _claimStEthViaWQ(unstEthIds, ethAmount); _withdrawalQueue.setLastFinalizedRequestId(0); @@ -929,7 +1088,7 @@ contract EscrowUnitTests is UnitTest { function test_claimUnstETH_HappyPath() external { uint256[] memory unstEthAmounts = new uint256[](1); - unstEthAmounts[0] = 1 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); uint256[] memory unstEthIds = _vetoerLockedUnstEth(unstEthAmounts); uint256[] memory hints = _finalizeUnstEth(unstEthAmounts, unstEthIds); @@ -949,7 +1108,9 @@ contract EscrowUnitTests is UnitTest { assertEq(state.unstETHIdsCount, 1); assertEq(state.stETHLockedShares.toUint256(), 0); - assertEq(state.unstETHLockedShares.toUint256(), unstEthAmounts[0]); + assertApproxEqAbs( + state.unstETHLockedShares.toUint256(), _stETH.getSharesByPooledEth(unstEthAmounts[0]), ACCURACY + ); } function test_claimUnstETH_RevertOn_UnexpectedEscrowState() external { @@ -974,7 +1135,7 @@ contract EscrowUnitTests is UnitTest { uint256[] memory unstETHIds = new uint256[](2); uint256[] memory hints = new uint256[](1); uint256[] memory responses = new uint256[](1); - responses[0] = 1 ether; + responses[0] = _stETH.getPooledEthByShares(1 ether); _transitToRageQuit(); @@ -986,7 +1147,7 @@ contract EscrowUnitTests is UnitTest { function test_claimUnstETH_RevertOn_InvalidUnstETHStatus() external { uint256[] memory unstEthAmounts = new uint256[](1); - unstEthAmounts[0] = 1 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); uint256[] memory unstEthIds = new uint256[](1); unstEthIds[0] = Random.nextUint256(_random, 100500); @@ -1034,16 +1195,17 @@ contract EscrowUnitTests is UnitTest { // --- function test_withdrawETH_HappyPath() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); - _claimStEthViaWQ(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); + _claimStEthViaWQ(unstEthIds, ethAmount); _ensureRageQuitExtensionPeriodStartedNow(); assertTrue(_escrow.getRageQuitEscrowDetails().isRageQuitExtensionPeriodStarted); @@ -1051,16 +1213,18 @@ contract EscrowUnitTests is UnitTest { vm.startPrank(_vetoer); vm.expectEmit(); - emit AssetsAccounting.ETHWithdrawn(_vetoer, SharesValues.from(stethAmount), ETHValues.from(stethAmount)); + emit AssetsAccounting.ETHWithdrawn( + _vetoer, SharesValues.from(_stETH.getSharesByPooledEth(ethAmount)), ETHValues.from(ethAmount) + ); _escrow.withdrawETH(); vm.stopPrank(); - assertEq(_vetoer.balance, balanceBefore + stethAmount); + assertEq(_vetoer.balance, balanceBefore + ethAmount); IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); - assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), stethAmount); - assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), stethAmount); + assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), _stETH.getSharesByPooledEth(ethAmount)); + assertEq(signallingEscrowDetails.totalStETHClaimedETH.toUint256(), ethAmount); assertEq(signallingEscrowDetails.totalUnstETHUnfinalizedShares.toUint256(), 0); assertEq(signallingEscrowDetails.totalUnstETHFinalizedETH.toUint256(), 0); @@ -1086,16 +1250,17 @@ contract EscrowUnitTests is UnitTest { } function test_withdrawETH_RevertOn_EthWithdrawalsDelayNotPassed() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(Durations.from(1), Durations.from(2)); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); - _claimStEthViaWQ(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); + _claimStEthViaWQ(unstEthIds, ethAmount); _ensureRageQuitExtensionPeriodStartedNow(); assertTrue(_escrow.getRageQuitEscrowDetails().isRageQuitExtensionPeriodStarted); @@ -1108,29 +1273,32 @@ contract EscrowUnitTests is UnitTest { } function test_withdrawETH_RevertOn_InvalidSharesValue() external { + uint256 ethAmount1 = _stETH.getPooledEthByShares(stethAmount); + uint256 sharesAmount2 = 100 ether; + uint256 ethAmount2 = _stETH.getPooledEthByShares(sharesAmount2); uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); address _vetoer2 = makeAddr("vetoer2"); - _stETH.mint(_vetoer2, 100 ether); + _stETH.mint(_vetoer2, ethAmount2); vm.startPrank(_vetoer2); _stETH.approve(address(_escrow), type(uint256).max); - _escrow.lockStETH(100 ether); + _escrow.lockStETH(ethAmount2); vm.stopPrank(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount1); _wait(_minLockAssetDuration.plusSeconds(1)); - _vetoerUnlockedStEth(stethAmount); + _vetoerUnlockedStEth(ethAmount1); _transitToRageQuit(); _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); - _claimStEthViaWQ(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); + _claimStEthViaWQ(unstEthIds, ethAmount1); _ensureRageQuitExtensionPeriodStartedNow(); assertTrue(_escrow.getRageQuitEscrowDetails().isRageQuitExtensionPeriodStarted); @@ -1151,8 +1319,8 @@ contract EscrowUnitTests is UnitTest { function test_withdrawETH_2_HappyPath() external { uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); uint256[] memory unstEthIds = _vetoerLockedUnstEth(unstEthAmounts); uint256[] memory hints = _finalizeUnstEth(unstEthAmounts, unstEthIds); @@ -1187,7 +1355,11 @@ contract EscrowUnitTests is UnitTest { assertEq(state.unstETHIdsCount, 2); assertEq(state.stETHLockedShares.toUint256(), 0); - assertEq(state.unstETHLockedShares.toUint256(), unstEthAmounts[0] + unstEthAmounts[1]); + assertApproxEqAbs( + state.unstETHLockedShares.toUint256(), + _stETH.getSharesByPooledEth(unstEthAmounts[0] + unstEthAmounts[1]), + ACCURACY + ); } function test_withdrawETH_2_RevertOn_EmptyUnstETHIds() external { @@ -1212,8 +1384,8 @@ contract EscrowUnitTests is UnitTest { function test_withdrawETH_2_RevertOn_EthWithdrawalsDelayNotPassed() external { uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); uint256[] memory unstEthIds = _vetoerLockedUnstEth(unstEthAmounts); uint256[] memory hints = _finalizeUnstEth(unstEthAmounts, unstEthIds); @@ -1240,8 +1412,8 @@ contract EscrowUnitTests is UnitTest { function test_withdrawETH_2_RevertOn_InvalidUnstETHStatus() external { uint256 balanceBefore = _vetoer.balance; uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); uint256[] memory unstEthIds = _vetoerLockedUnstEth(unstEthAmounts); _finalizeUnstEth(unstEthAmounts, unstEthIds); @@ -1268,10 +1440,10 @@ contract EscrowUnitTests is UnitTest { } // --- - // getLockedAssetsTotals() + // getSignallingEscrowDetails() // --- - function test_getLockedAssetsTotals() external view { + function test_getSignallingEscrowDetails() external view { IEscrow.SignallingEscrowDetails memory signallingEscrowDetails = _escrow.getSignallingEscrowDetails(); assertEq(signallingEscrowDetails.totalStETHLockedShares.toUint256(), 0); @@ -1281,16 +1453,16 @@ contract EscrowUnitTests is UnitTest { } // --- - // getVetoerState() + // getVetoerDetails() // --- - function test_getVetoerState() external { - _vetoerLockedStEth(stethAmount); + function test_getVetoerDetails() external { + _vetoerLockedStEth(_stETH.getPooledEthByShares(stethAmount)); IEscrow.VetoerDetails memory state = _escrow.getVetoerDetails(_vetoer); assertEq(state.unstETHIdsCount, 0); - assertEq(state.stETHLockedShares.toUint256(), _stETH.getSharesByPooledEth(stethAmount)); + assertApproxEqAbs(state.stETHLockedShares.toUint256(), stethAmount, ACCURACY); assertEq(state.unstETHLockedShares.toUint256(), 0); assertEq(state.lastAssetsLockTimestamp, Timestamps.now()); } @@ -1301,8 +1473,8 @@ contract EscrowUnitTests is UnitTest { function test_getVetoerUnstETHIds() external { uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); assertEq(_escrow.getVetoerUnstETHIds(_vetoer).length, 0); @@ -1339,8 +1511,8 @@ contract EscrowUnitTests is UnitTest { function test_getLockedUnstETHDetails_HappyPath() external { uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); assertEq(_escrow.getVetoerUnstETHIds(_vetoer).length, 0); @@ -1353,13 +1525,13 @@ contract EscrowUnitTests is UnitTest { assertEq(unstETHDetails[0].id, unstEthIds[0]); assertEq(unstETHDetails[0].lockedBy, _vetoer); assertTrue(unstETHDetails[0].status == UnstETHRecordStatus.Locked); - assertEq(unstETHDetails[0].shares.toUint256(), unstEthAmounts[0]); + assertEq(unstETHDetails[0].shares.toUint256(), _stETH.getSharesByPooledEth(unstEthAmounts[0])); assertEq(unstETHDetails[0].claimableAmount.toUint256(), 0); assertEq(unstETHDetails[1].id, unstEthIds[1]); assertEq(unstETHDetails[1].lockedBy, _vetoer); assertTrue(unstETHDetails[1].status == UnstETHRecordStatus.Locked); - assertEq(unstETHDetails[1].shares.toUint256(), unstEthAmounts[1]); + assertEq(unstETHDetails[1].shares.toUint256(), _stETH.getSharesByPooledEth(unstEthAmounts[1])); assertEq(unstETHDetails[1].claimableAmount.toUint256(), 0); } @@ -1382,9 +1554,10 @@ contract EscrowUnitTests is UnitTest { // --- function test_getNextWithdrawalBatch() external { + uint256 ethAmount = _stETH.getPooledEthByShares(stethAmount); uint256[] memory unstEthIds = _getUnstEthIdsFromWQ(); - _vetoerLockedStEth(stethAmount); + _vetoerLockedStEth(ethAmount); _transitToRageQuit(); @@ -1394,19 +1567,19 @@ contract EscrowUnitTests is UnitTest { _withdrawalQueue.setRequestWithdrawalsResult(unstEthIds); _withdrawalQueue.setLastCheckpointIndex(1); _withdrawalQueue.setCheckpointHints(new uint256[](unstEthIds.length)); - _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds, stethAmount); + _ensureUnstEthAddedToWithdrawalsBatchesQueue(unstEthIds); claimableUnstEthIds = _escrow.getNextWithdrawalBatch(100); assertEq(claimableUnstEthIds.length, unstEthIds.length); assertEq(claimableUnstEthIds[0], unstEthIds[0]); - _withdrawalQueue.setClaimableAmount(stethAmount); - vm.deal(address(_withdrawalQueue), stethAmount); + _withdrawalQueue.setClaimableAmount(ethAmount); + vm.deal(address(_withdrawalQueue), ethAmount); vm.expectEmit(); emit WithdrawalsBatchesQueue.UnstETHIdsClaimed(unstEthIds); vm.expectEmit(); - emit AssetsAccounting.ETHClaimed(ETHValues.from(stethAmount)); + emit AssetsAccounting.ETHClaimed(ETHValues.from(ethAmount)); _escrow.claimNextWithdrawalsBatch(unstEthIds[0], new uint256[](unstEthIds.length)); claimableUnstEthIds = _escrow.getNextWithdrawalBatch(100); @@ -1483,57 +1656,16 @@ contract EscrowUnitTests is UnitTest { _masterCopy.getUnclaimedUnstETHIdsCount(); } - // --- - // isRageQuitExtensionPeriodStarted() - // --- - - function test_isRageQuitExtensionPeriodStarted() external { - _transitToRageQuit(); - - assertFalse(_escrow.getRageQuitEscrowDetails().isRageQuitExtensionPeriodStarted); - - _ensureWithdrawalsBatchesQueueClosed(); - - _ensureRageQuitExtensionPeriodStartedNow(); - - assertTrue(_escrow.getRageQuitEscrowDetails().isRageQuitExtensionPeriodStarted); - - assertEq(_escrow.getRageQuitEscrowDetails().rageQuitExtensionPeriodStartedAt, Timestamps.now()); - } - - // --- - // getRageQuitExtensionPeriodStartedAt() - // --- - - function test_getRageQuitExtensionPeriodStartedAt_RevertOn_NotInitializedState() external { - vm.expectRevert( - abi.encodeWithSelector(EscrowStateLib.UnexpectedEscrowState.selector, EscrowState.NotInitialized) - ); - _masterCopy.getRageQuitEscrowDetails(); - } - - function test_getRageQuitExtensionPeriodStartedAt_RevertOn_SignallingState() external { - vm.expectRevert( - abi.encodeWithSelector(EscrowStateLib.UnexpectedEscrowState.selector, EscrowState.SignallingEscrow) - ); - _escrow.getRageQuitEscrowDetails().rageQuitExtensionPeriodStartedAt; - } - - function test_getRageQuitExtensionPeriodStartedAt() external { - _transitToRageQuit(); - Timestamp res = _escrow.getRageQuitEscrowDetails().rageQuitExtensionPeriodStartedAt; - assertEq(res.toSeconds(), Timestamps.ZERO.toSeconds()); - } - // --- // getRageQuitSupport() // --- function test_getRageQuitSupport() external { - uint256 stEthLockedAmount = 80 ether + 100 wei; + uint256 stEthLockedShares = 80 ether; + uint256 stEthLockedAmount = _stETH.getPooledEthByShares(stEthLockedShares); uint256[] memory unstEthAmounts = new uint256[](2); - unstEthAmounts[0] = 1 ether; - unstEthAmounts[1] = 10 ether; + unstEthAmounts[0] = _stETH.getPooledEthByShares(1 ether); + unstEthAmounts[1] = _stETH.getPooledEthByShares(10 ether); uint256[] memory finalizedUnstEthAmounts = new uint256[](1); uint256[] memory finalizedUnstEthIds = new uint256[](1); @@ -1543,8 +1675,8 @@ contract EscrowUnitTests is UnitTest { _vetoerLockedStEth(stEthLockedAmount); PercentD16 support = _escrow.getRageQuitSupport(); - assertEq(support, actualSupport); - assertEq(support, PercentsD16.fromBasisPoints(80_00)); + assertApproxEqAbs(support.toUint256(), actualSupport.toUint256(), ACCURACY); + assertApproxEqAbs(support.toUint256(), PercentsD16.fromBasisPoints(80_00).toUint256(), ACCURACY); // When some unstEth are locked in escrow => rage quit support changed @@ -1561,8 +1693,8 @@ contract EscrowUnitTests is UnitTest { }); support = _escrow.getRageQuitSupport(); - assertEq(support, actualSupport); - assertEq(support, PercentsD16.fromBasisPoints(91_00)); + assertApproxEqAbs(support.toUint256(), actualSupport.toUint256(), ACCURACY); + assertApproxEqAbs(support.toUint256(), PercentsD16.fromBasisPoints(91_00).toUint256(), ACCURACY); } // --- @@ -1585,6 +1717,26 @@ contract EscrowUnitTests is UnitTest { // getRageQuitEscrowDetails() // --- + function test_getRageQuitEscrowDetails_HappyPath() external { + _transitToRageQuit(); + + IRageQuitEscrow.RageQuitEscrowDetails memory details = _escrow.getRageQuitEscrowDetails(); + assertFalse(details.isRageQuitExtensionPeriodStarted); + assertEq(details.rageQuitExtensionPeriodStartedAt, Timestamps.ZERO); + assertEq(details.rageQuitEthWithdrawalsDelay, Durations.ZERO); + assertEq(details.rageQuitExtensionPeriodDuration, Durations.ZERO); + + _ensureWithdrawalsBatchesQueueClosed(); + + _ensureRageQuitExtensionPeriodStartedNow(); + + details = _escrow.getRageQuitEscrowDetails(); + assertTrue(details.isRageQuitExtensionPeriodStarted); + assertEq(details.rageQuitExtensionPeriodStartedAt, Timestamps.now()); + assertEq(details.rageQuitEthWithdrawalsDelay, Durations.ZERO); + assertEq(details.rageQuitExtensionPeriodDuration, Durations.ZERO); + } + function test_getRageQuitEscrowDetails_RevertOn_UnexpectedEscrowState_Signaling() external { vm.expectRevert( abi.encodeWithSelector(EscrowStateLib.UnexpectedEscrowState.selector, EscrowState.SignallingEscrow) @@ -1629,11 +1781,12 @@ contract EscrowUnitTests is UnitTest { // MIN_TRANSFERRABLE_ST_ETH_AMOUNT // --- - function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT() external { + function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT() external view { assertEq(_escrow.MIN_TRANSFERRABLE_ST_ETH_AMOUNT(), 100); } function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT_gt_minWithdrawableStETHAmountWei_HappyPath() external { + _stETH.setTotalPooledEther(stethInitialEthAmount); uint256 amountToLock = 100; uint256 minWithdrawableStETHAmountWei = 99; @@ -1663,6 +1816,7 @@ contract EscrowUnitTests is UnitTest { } function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT_gt_minWithdrawableStETHAmountWei_HappyPath_closes_queue() external { + _stETH.setTotalPooledEther(stethInitialEthAmount); uint256 amountToLock = 99; uint256 minWithdrawableStETHAmountWei = 99; @@ -1691,6 +1845,7 @@ contract EscrowUnitTests is UnitTest { } function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT_lt_minWithdrawableStETHAmountWei_HappyPath() external { + _stETH.setTotalPooledEther(stethInitialEthAmount); uint256 amountToLock = 101; uint256 minWithdrawableStETHAmountWei = 101; @@ -1720,6 +1875,7 @@ contract EscrowUnitTests is UnitTest { } function test_MIN_TRANSFERRABLE_ST_ETH_AMOUNT_lt_minWithdrawableStETHAmountWei_HappyPath_closes_queue() external { + _stETH.setTotalPooledEther(stethInitialEthAmount); uint256 amountToLock = 100; uint256 minWithdrawableStETHAmountWei = 101; @@ -1784,20 +1940,21 @@ contract EscrowUnitTests is UnitTest { _escrow.startRageQuit(rqExtensionPeriod, rqEthWithdrawalsDelay); } - function _vetoerLockedStEth(uint256 amount) internal { + function _vetoerLockedStEth(uint256 ethAmount) internal { vm.prank(_vetoer); - _escrow.lockStETH(amount); + _escrow.lockStETH(ethAmount); } - function _vetoerLockedUnstEth(uint256[] memory amounts) internal returns (uint256[] memory unstethIds) { - unstethIds = new uint256[](amounts.length); + function _vetoerLockedUnstEth(uint256[] memory ethAmounts) internal returns (uint256[] memory unstethIds) { + unstethIds = new uint256[](ethAmounts.length); IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = - new IWithdrawalQueue.WithdrawalRequestStatus[](amounts.length); + new IWithdrawalQueue.WithdrawalRequestStatus[](ethAmounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { + for (uint256 i = 0; i < ethAmounts.length; ++i) { unstethIds[i] = i; - statuses[i] = - IWithdrawalQueue.WithdrawalRequestStatus(amounts[i], amounts[i], _vetoer, block.timestamp, false, false); + statuses[i] = IWithdrawalQueue.WithdrawalRequestStatus( + ethAmounts[i], _stETH.getSharesByPooledEth(ethAmounts[i]), _vetoer, block.timestamp, false, false + ); } _withdrawalQueue.setWithdrawalRequestsStatuses(statuses); @@ -1807,43 +1964,43 @@ contract EscrowUnitTests is UnitTest { } function _finalizeUnstEth( - uint256[] memory amounts, + uint256[] memory ethAmounts, uint256[] memory finalizedUnstEthIds ) internal returns (uint256[] memory hints) { - assertEq(amounts.length, finalizedUnstEthIds.length); + assertEq(ethAmounts.length, finalizedUnstEthIds.length); - hints = new uint256[](amounts.length); - uint256[] memory responses = new uint256[](amounts.length); + hints = new uint256[](ethAmounts.length); + uint256[] memory responses = new uint256[](ethAmounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { + for (uint256 i = 0; i < ethAmounts.length; ++i) { hints[i] = i; - responses[i] = amounts[i]; + responses[i] = ethAmounts[i]; } _withdrawalQueue.setClaimableEtherResult(responses); _escrow.markUnstETHFinalized(finalizedUnstEthIds, hints); - for (uint256 i = 0; i < amounts.length; ++i) { - _stETH.burn(_vetoer, amounts[i]); + for (uint256 i = 0; i < ethAmounts.length; ++i) { + _stETH.burn(_vetoer, ethAmounts[i]); } } function _claimUnstEthFromEscrow( - uint256[] memory amounts, + uint256[] memory ethAmounts, uint256[] memory unstEthIds, uint256[] memory hints ) internal returns (uint256 sum) { - assertEq(amounts.length, unstEthIds.length); - assertEq(amounts.length, hints.length); + assertEq(ethAmounts.length, unstEthIds.length); + assertEq(ethAmounts.length, hints.length); sum = 0; - for (uint256 i = 0; i < amounts.length; ++i) { - sum += amounts[i]; + for (uint256 i = 0; i < ethAmounts.length; ++i) { + sum += ethAmounts[i]; } _withdrawalQueue.setClaimableAmount(sum); - _withdrawalQueue.setClaimableEtherResult(amounts); + _withdrawalQueue.setClaimableEtherResult(ethAmounts); vm.deal(address(_withdrawalQueue), sum); vm.expectEmit(); @@ -1851,33 +2008,33 @@ contract EscrowUnitTests is UnitTest { _escrow.claimUnstETH(unstEthIds, hints); } - function _claimStEthViaWQ(uint256[] memory unstEthIds, uint256 amount) internal { - _withdrawalQueue.setClaimableAmount(amount); + function _claimStEthViaWQ(uint256[] memory unstEthIds, uint256 ethAmount) internal { + _withdrawalQueue.setClaimableAmount(ethAmount); _withdrawalQueue.setLastCheckpointIndex(1); _withdrawalQueue.setCheckpointHints(new uint256[](unstEthIds.length)); - vm.deal(address(_withdrawalQueue), amount); + vm.deal(address(_withdrawalQueue), ethAmount); vm.expectEmit(); emit WithdrawalsBatchesQueue.UnstETHIdsClaimed(unstEthIds); vm.expectEmit(); - emit AssetsAccounting.ETHClaimed(ETHValues.from(amount)); + emit AssetsAccounting.ETHClaimed(ETHValues.from(ethAmount)); _escrow.claimNextWithdrawalsBatch(unstEthIds.length); } - function _vetoerUnlockedStEth(uint256 amount) internal { + function _vetoerUnlockedStEth(uint256 ethAmount) internal { vm.startPrank(_vetoer); vm.expectEmit(); - emit AssetsAccounting.StETHSharesUnlocked(_vetoer, SharesValues.from(_stETH.getSharesByPooledEth(amount))); + emit AssetsAccounting.StETHSharesUnlocked(_vetoer, SharesValues.from(_stETH.getSharesByPooledEth(ethAmount))); _escrow.unlockStETH(); vm.stopPrank(); } - function _ensureUnstEthAddedToWithdrawalsBatchesQueue(uint256[] memory unstEthIds, uint256 ethAmount) internal { + function _ensureUnstEthAddedToWithdrawalsBatchesQueue(uint256[] memory unstEthIds) internal { vm.expectEmit(); emit WithdrawalsBatchesQueue.UnstETHIdsAdded(unstEthIds); _escrow.requestNextWithdrawalsBatch(100); - assertEq(_stETH.balanceOf(address(_escrow)), 0); + assertApproxEqAbs(_stETH.balanceOf(address(_escrow)), 0, ACCURACY); } function _ensureWithdrawalsBatchesQueueClosed() internal { @@ -1900,4 +2057,19 @@ contract EscrowUnitTests is UnitTest { unstEthIds = new uint256[](1); unstEthIds[0] = lri + 1; } + + function _percentD16ToString(PercentD16 number) internal view returns (string memory) { + uint256 intPart = number.toUint256() / ONE_PERCENT_D16; + uint256 fractionalPart = number.toUint256() - intPart * ONE_PERCENT_D16; + + string memory fractionalChars; + for (uint256 i = 0; i < 16; ++i) { + uint256 divider = 10 ** (15 - i); + uint256 char = fractionalPart / divider; + fractionalChars = string.concat(fractionalChars, vm.toString(char)); + fractionalPart -= char * divider; + } + + return string.concat(vm.toString(intPart), ".", fractionalChars); + } } diff --git a/test/unit/libraries/SealableCalls.t.sol b/test/unit/libraries/SealableCalls.t.sol index cc47581e..1a966195 100644 --- a/test/unit/libraries/SealableCalls.t.sol +++ b/test/unit/libraries/SealableCalls.t.sol @@ -6,6 +6,8 @@ import {ISealable, SealableCalls} from "contracts/libraries/SealableCalls.sol"; import {UnitTest} from "test/utils/unit-test.sol"; +uint256 constant BLOCK_GAS_LIMIT = 30_000_000; + error CustomSealableError(string message); contract SealableCallsTest is UnitTest { @@ -104,11 +106,11 @@ contract SealableCallsTest is UnitTest { } // --- - // Other Precompiles (Split in 2 parts because of out of gas) + // Other Precompile Calls Are Not Successful // --- - function test_callGetResumeSinceTimestamp_IsCallSucceed_CorrectResult_On_Other_Precompiles_Part1() external { - for (uint160 i = 1; i < 8; ++i) { + function test_callGetResumeSinceTimestamp_IsCallSucceed_CorrectResult_On_Other_Precompiles() external { + for (uint160 i = 1; i < 12; ++i) { // Skip SHA-256 and RIPEMD-160 precompiles which lead to false positive results if (i == 0x2 || i == 0x3) continue; _assertGetResumeSinceTimestampCallResult({ @@ -119,16 +121,6 @@ contract SealableCallsTest is UnitTest { } } - function test_callGetResumeSinceTimestamp_IsCallSucceed_CorrectResult_On_Other_Precompiles_Part2() external { - for (uint160 i = 8; i < 12; ++i) { - _assertGetResumeSinceTimestampCallResult({ - sealable: address(i), - isCallSucceed: false, - resumeSinceTimestamp: 0 - }); - } - } - // --- // Helper Test Methods // --- @@ -147,7 +139,8 @@ contract SealableCallsTest is UnitTest { uint256 resumeSinceTimestamp ) internal { (bool isCallSucceedActual, uint256 resumeSinceTimestampActual) = - SealableCalls.callGetResumeSinceTimestamp(sealable); + // Limit the maximum gas cost for the call to mimic mainnet behavior + this.external__getResumeSinceTimestampCall{gas: BLOCK_GAS_LIMIT}(sealable); assertEq(isCallSucceedActual, isCallSucceed, "Unexpected isCallSucceed value"); assertEq(resumeSinceTimestampActual, resumeSinceTimestamp, "Unexpected resumeSinceTimestamp value"); @@ -156,4 +149,8 @@ contract SealableCallsTest is UnitTest { function _mockSealableResumeSinceTimestampReverts(address sealable, bytes memory revertReason) internal { vm.mockCallRevert(sealable, abi.encodeWithSelector(ISealable.getResumeSinceTimestamp.selector), revertReason); } + + function external__getResumeSinceTimestampCall(address sealable) external returns (bool, uint256) { + return SealableCalls.callGetResumeSinceTimestamp(sealable); + } } diff --git a/test/utils/SetupDeployment.sol b/test/utils/SetupDeployment.sol deleted file mode 100644 index 24500c7a..00000000 --- a/test/utils/SetupDeployment.sol +++ /dev/null @@ -1,361 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {Test} from "forge-std/Test.sol"; - -// --- -// Types -// --- - -import {PercentsD16} from "contracts/types/PercentD16.sol"; -import {Durations, Duration} from "contracts/types/Duration.sol"; -import {Timestamps} from "contracts/types/Timestamp.sol"; - -// --- -// Interfaces -// --- -import {ITimelock} from "contracts/interfaces/ITimelock.sol"; -import {IResealManager} from "contracts/interfaces/IResealManager.sol"; - -// --- -// Contracts -// --- -import {TargetMock} from "./target-mock.sol"; - -import {Executor} from "contracts/Executor.sol"; -import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; - -import {TimelockedGovernance} from "contracts/TimelockedGovernance.sol"; - -import {ResealManager} from "contracts/ResealManager.sol"; -import {DualGovernance} from "contracts/DualGovernance.sol"; -import { - IDualGovernanceConfigProvider, - ImmutableDualGovernanceConfigProvider -} from "contracts/ImmutableDualGovernanceConfigProvider.sol"; - -import {TiebreakerCoreCommittee} from "contracts/committees/TiebreakerCoreCommittee.sol"; -import {TiebreakerSubCommittee} from "contracts/committees/TiebreakerSubCommittee.sol"; -// --- -// Util Libraries -// --- - -import {Random} from "./random.sol"; -import {LidoUtils} from "./lido-utils.sol"; -import {DeployConfig, LidoContracts} from "../../scripts/deploy/config/Config.sol"; -import {DeployedContracts} from "../../scripts/deploy/DeployedContractsSet.sol"; -import {DGContractsDeployment} from "../../scripts/deploy/ContractsDeployment.sol"; - -// --- -// Lido Addresses -// --- - -abstract contract SetupDeployment is Test { - using Random for Random.Context; - // --- - // Helpers - // --- - - DeployConfig internal _dgDeployConfig; - LidoContracts internal _lidoAddresses; - DeployedContracts internal _contracts; - - Random.Context internal _random; - LidoUtils.Context internal _lido; - - // --- - // Emergency Protected Timelock Deployment Parameters - // --- - - // TODO: consider to use non zero value for the more realistic setup in the tests - Duration internal immutable _MIN_EXECUTION_DELAY = Durations.ZERO; - Duration internal immutable _AFTER_SUBMIT_DELAY = Durations.from(3 days); - Duration internal immutable _MAX_AFTER_SUBMIT_DELAY = Durations.from(45 days); - - Duration internal immutable _AFTER_SCHEDULE_DELAY = Durations.from(3 days); - Duration internal immutable _MAX_AFTER_SCHEDULE_DELAY = Durations.from(45 days); - - Duration internal immutable _EMERGENCY_MODE_DURATION = Durations.from(180 days); - Duration internal immutable _MAX_EMERGENCY_MODE_DURATION = Durations.from(365 days); - - Duration internal immutable _EMERGENCY_PROTECTION_DURATION = Durations.from(90 days); - Duration internal immutable _MAX_EMERGENCY_PROTECTION_DURATION = Durations.from(365 days); - - uint256 internal immutable _EMERGENCY_ACTIVATION_COMMITTEE_QUORUM = 3; - uint256 internal immutable _EMERGENCY_ACTIVATION_COMMITTEE_MEMBERS_COUNT = 5; - - uint256 internal immutable _EMERGENCY_EXECUTION_COMMITTEE_QUORUM = 5; - uint256 internal immutable _EMERGENCY_EXECUTION_COMMITTEE_MEMBERS_COUNT = 8; - - // --- - // Dual Governance Deployment Parameters - // --- - uint256 internal immutable TIEBREAKER_CORE_QUORUM = 2; - Duration internal immutable TIEBREAKER_EXECUTION_DELAY = Durations.from(30 days); - - uint256 internal immutable TIEBREAKER_SUB_COMMITTEE_MEMBERS_COUNT = 5; - uint256 internal immutable TIEBREAKER_SUB_COMMITTEE_QUORUM = 5; - - Duration internal immutable MIN_TIEBREAKER_ACTIVATION_TIMEOUT = Durations.from(90 days); - Duration internal immutable TIEBREAKER_ACTIVATION_TIMEOUT = Durations.from(365 days); - Duration internal immutable MAX_TIEBREAKER_ACTIVATION_TIMEOUT = Durations.from(730 days); - uint256 internal immutable MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT = 255; - - uint256 internal FORK_BLOCK_NUMBER = 20218312; - uint256 internal FORK_BLOCK_TIMESTAMP = 1719917015; - - // - - // --- - // Emergency Protected Timelock Contracts - // --- - Executor internal _adminExecutor; - EmergencyProtectedTimelock internal _timelock; - TimelockedGovernance internal _timelockedGovernance; - address internal _emergencyActivationCommittee; - address internal _emergencyExecutionCommittee; - // --- - // Timelocked Governance Contracts - // --- - TimelockedGovernance internal _emergencyGovernance; - TimelockedGovernance internal _temporaryEmergencyGovernance; - address internal _temporaryEmergencyGovernanceProposer; - - // --- - // Dual Governance Contracts - // --- - ResealManager internal _resealManager; - DualGovernance internal _dualGovernance; - ImmutableDualGovernanceConfigProvider internal _dualGovernanceConfigProvider; - - address internal _resealCommittee; - TiebreakerCoreCommittee internal _tiebreakerCoreCommittee; - TiebreakerSubCommittee[] internal _tiebreakerSubCommittees; - - // --- - // Target Mock Helper Contract - // --- - - TargetMock internal _targetMock; - - // --- - // Constructor - // --- - - constructor(LidoUtils.Context memory lido, Random.Context memory random) { - _lido = lido; - _random = random; - _targetMock = new TargetMock(); - - _emergencyActivationCommittee = makeAddr("EMERGENCY_ACTIVATION_COMMITTEE"); - _emergencyExecutionCommittee = makeAddr("EMERGENCY_EXECUTION_COMMITTEE"); - _resealCommittee = makeAddr("RESEAL_COMMITTEE"); - _temporaryEmergencyGovernanceProposer = makeAddr("TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER"); - - _dgDeployConfig.MIN_EXECUTION_DELAY = _dgDeployConfig.AFTER_SUBMIT_DELAY = _AFTER_SUBMIT_DELAY; - _dgDeployConfig.MAX_AFTER_SUBMIT_DELAY = _MAX_AFTER_SUBMIT_DELAY; - _dgDeployConfig.AFTER_SCHEDULE_DELAY = _AFTER_SCHEDULE_DELAY; - _dgDeployConfig.MAX_AFTER_SCHEDULE_DELAY = _MAX_AFTER_SCHEDULE_DELAY; - _dgDeployConfig.EMERGENCY_MODE_DURATION = _EMERGENCY_MODE_DURATION; - _dgDeployConfig.MAX_EMERGENCY_MODE_DURATION = _MAX_EMERGENCY_MODE_DURATION; - _dgDeployConfig.EMERGENCY_PROTECTION_END_DATE = - _EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.from(FORK_BLOCK_TIMESTAMP)); - _dgDeployConfig.MAX_EMERGENCY_PROTECTION_DURATION = _MAX_EMERGENCY_PROTECTION_DURATION; - - _dgDeployConfig.EMERGENCY_ACTIVATION_COMMITTEE = _emergencyActivationCommittee; - _dgDeployConfig.EMERGENCY_EXECUTION_COMMITTEE = _emergencyExecutionCommittee; - - _dgDeployConfig.tiebreakerConfig.quorum = TIEBREAKER_CORE_QUORUM; - _dgDeployConfig.tiebreakerConfig.executionDelay = TIEBREAKER_EXECUTION_DELAY; - _dgDeployConfig.tiebreakerConfig.influencers.members = - _generateRandomAddresses(TIEBREAKER_SUB_COMMITTEE_MEMBERS_COUNT); - _dgDeployConfig.tiebreakerConfig.influencers.quorum = TIEBREAKER_SUB_COMMITTEE_QUORUM; - _dgDeployConfig.tiebreakerConfig.nodeOperators.members = - _generateRandomAddresses(TIEBREAKER_SUB_COMMITTEE_MEMBERS_COUNT); - _dgDeployConfig.tiebreakerConfig.nodeOperators.quorum = TIEBREAKER_SUB_COMMITTEE_QUORUM; - _dgDeployConfig.tiebreakerConfig.protocols.members = - _generateRandomAddresses(TIEBREAKER_SUB_COMMITTEE_MEMBERS_COUNT); - _dgDeployConfig.tiebreakerConfig.protocols.quorum = TIEBREAKER_SUB_COMMITTEE_QUORUM; - - _dgDeployConfig.RESEAL_COMMITTEE = _resealCommittee; - - _dgDeployConfig.MIN_WITHDRAWALS_BATCH_SIZE = 4; - _dgDeployConfig.tiebreakerConfig.minActivationTimeout = MIN_TIEBREAKER_ACTIVATION_TIMEOUT; - _dgDeployConfig.tiebreakerConfig.activationTimeout = TIEBREAKER_ACTIVATION_TIMEOUT; - _dgDeployConfig.tiebreakerConfig.maxActivationTimeout = MAX_TIEBREAKER_ACTIVATION_TIMEOUT; - _dgDeployConfig.MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT = MAX_SEALABLE_WITHDRAWAL_BLOCKERS_COUNT; - _dgDeployConfig.FIRST_SEAL_RAGE_QUIT_SUPPORT = PercentsD16.fromBasisPoints(3_00); // 3% - _dgDeployConfig.SECOND_SEAL_RAGE_QUIT_SUPPORT = PercentsD16.fromBasisPoints(15_00); // 15% - _dgDeployConfig.MIN_ASSETS_LOCK_DURATION = Durations.from(5 hours); - _dgDeployConfig.VETO_SIGNALLING_MIN_DURATION = Durations.from(3 days); - _dgDeployConfig.VETO_SIGNALLING_MAX_DURATION = Durations.from(30 days); - _dgDeployConfig.VETO_SIGNALLING_MIN_ACTIVE_DURATION = Durations.from(5 hours); - _dgDeployConfig.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION = Durations.from(5 days); - _dgDeployConfig.VETO_COOLDOWN_DURATION = Durations.from(4 days); - _dgDeployConfig.RAGE_QUIT_EXTENSION_PERIOD_DURATION = Durations.from(7 days); - _dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MIN_DELAY = Durations.from(30 days); - _dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_MAX_DELAY = Durations.from(180 days); - _dgDeployConfig.RAGE_QUIT_ETH_WITHDRAWALS_DELAY_GROWTH = Durations.from(15 days); - _dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER = _temporaryEmergencyGovernanceProposer; - - _dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER = _temporaryEmergencyGovernanceProposer; - - _lidoAddresses.stETH = _lido.stETH; - _lidoAddresses.wstETH = _lido.wstETH; - _lidoAddresses.withdrawalQueue = _lido.withdrawalQueue; - _lidoAddresses.voting = address(_lido.voting); - } - - // --- - // Whole Setup Deployments - // --- - - function _deployTimelockedGovernanceSetup(bool isEmergencyProtectionEnabled) internal { - _deployEmergencyProtectedTimelockContracts(isEmergencyProtectionEnabled, false); - _timelockedGovernance = - DGContractsDeployment.deployTimelockedGovernance({governance: address(_lido.voting), timelock: _timelock}); - DGContractsDeployment.finalizeEmergencyProtectedTimelockDeploy( - _adminExecutor, _timelock, address(_timelockedGovernance) - ); - } - - function _deployDualGovernanceSetup(bool isEmergencyProtectionEnabled) internal { - _deployDualGovernanceSetup(isEmergencyProtectionEnabled, false); - } - - function _deployDualGovernanceSetup( - bool isEmergencyProtectionEnabled, - bool useTemporaryEmergencyGovernance - ) internal { - _deployEmergencyProtectedTimelockContracts(isEmergencyProtectionEnabled, useTemporaryEmergencyGovernance); - _resealManager = _deployResealManager(_timelock); - _contracts.resealManager = _resealManager; - _dualGovernanceConfigProvider = _deployDualGovernanceConfigProvider(); - _dualGovernance = _deployDualGovernance({ - timelock: _timelock, - resealManager: _resealManager, - configProvider: _dualGovernanceConfigProvider - }); - _contracts.dualGovernance = _dualGovernance; - - _tiebreakerCoreCommittee = DGContractsDeployment.deployEmptyTiebreakerCoreCommittee({ - owner: address(this), // temporary set owner to deployer, to add sub committees manually - dualGovernance: address(_dualGovernance), - executionDelay: TIEBREAKER_EXECUTION_DELAY - }); - _contracts.tiebreakerCoreCommittee = _tiebreakerCoreCommittee; - - (TiebreakerSubCommittee influencers, TiebreakerSubCommittee nodeOperators, TiebreakerSubCommittee protocols) = - DGContractsDeployment.deployTiebreakerSubCommittees( - address(_adminExecutor), _tiebreakerCoreCommittee, _dgDeployConfig - ); - _contracts.tiebreakerSubCommitteeInfluencers = influencers; - _contracts.tiebreakerSubCommitteeNodeOperators = nodeOperators; - _contracts.tiebreakerSubCommitteeProtocols = protocols; - - _tiebreakerSubCommittees = new TiebreakerSubCommittee[](3); - _tiebreakerSubCommittees[0] = influencers; - _tiebreakerSubCommittees[1] = nodeOperators; - _tiebreakerSubCommittees[2] = protocols; - - _tiebreakerCoreCommittee.transferOwnership(address(_adminExecutor)); - - // --- - // Finalize Setup - // --- - - DGContractsDeployment.configureDualGovernance(_dgDeployConfig, _lidoAddresses, _contracts); - DGContractsDeployment.finalizeEmergencyProtectedTimelockDeploy( - _adminExecutor, _timelock, address(_dualGovernance) - ); - - // --- - // Grant Reseal Manager Roles - // --- - vm.startPrank(address(_lido.agent)); - _lido.withdrawalQueue.grantRole( - 0x139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d, address(_resealManager) - ); - _lido.withdrawalQueue.grantRole( - 0x2fc10cc8ae19568712f7a176fb4978616a610650813c9d05326c34abb62749c7, address(_resealManager) - ); - vm.stopPrank(); - } - - // --- - // Emergency Protected Timelock Deployment - // --- - - function _deployEmergencyProtectedTimelockContracts( - bool isEmergencyProtectionEnabled, - bool useTemporaryEmergencyGovernance - ) internal { - DeployedContracts memory memContracts = - DGContractsDeployment.deployAdminExecutorAndTimelock(_dgDeployConfig, address(this)); - _adminExecutor = memContracts.adminExecutor; - _timelock = EmergencyProtectedTimelock(address(memContracts.timelock)); - - if (useTemporaryEmergencyGovernance == false) { - _dgDeployConfig.TEMPORARY_EMERGENCY_GOVERNANCE_PROPOSER = address(0); - } - - if (isEmergencyProtectionEnabled) { - (_emergencyGovernance, _temporaryEmergencyGovernance) = DGContractsDeployment - .deployEmergencyProtectedTimelockContracts(_lidoAddresses, _dgDeployConfig, memContracts); - } - _contracts.timelock = _timelock; - _contracts.adminExecutor = _adminExecutor; - _contracts.emergencyGovernance = _emergencyGovernance; - _contracts.temporaryEmergencyGovernance = _temporaryEmergencyGovernance; - } - - function _deployEmergencyProtectedTimelock(Executor adminExecutor) internal returns (EmergencyProtectedTimelock) { - return EmergencyProtectedTimelock( - address(DGContractsDeployment.deployEmergencyProtectedTimelock(address(adminExecutor), _dgDeployConfig)) - ); - } - - // --- - // Dual Governance Deployment - // --- - - function _deployDualGovernanceConfigProvider() internal returns (ImmutableDualGovernanceConfigProvider) { - return DGContractsDeployment.deployDualGovernanceConfigProvider(_dgDeployConfig); - } - - function _deployTimelockedGovernance( - address governance, - ITimelock timelock - ) internal returns (TimelockedGovernance) { - return new TimelockedGovernance(governance, timelock); - } - - // --- - // Dual Governance Deployment - // --- - - function _deployResealManager(ITimelock timelock) internal returns (ResealManager) { - return DGContractsDeployment.deployResealManager(timelock); - } - - function _deployDualGovernance( - ITimelock timelock, - IResealManager resealManager, - IDualGovernanceConfigProvider configProvider - ) internal returns (DualGovernance) { - return DGContractsDeployment.deployDualGovernance( - configProvider, timelock, resealManager, _dgDeployConfig, _lidoAddresses - ); - } - - // --- - // Helper methods - // --- - - function _generateRandomAddresses(uint256 count) internal returns (address[] memory addresses) { - addresses = new address[](count); - for (uint256 i = 0; i < count; ++i) { - addresses[i] = _random.nextAddress(); - } - } -} diff --git a/test/utils/executor-calls.sol b/test/utils/executor-calls.sol index 610d6035..9aeebf41 100644 --- a/test/utils/executor-calls.sol +++ b/test/utils/executor-calls.sol @@ -183,4 +183,12 @@ library ExternalCallHelpers { res[i].payload = payloads[i]; } } + + function create(address target, bytes[6] memory payloads) internal pure returns (ExternalCall[] memory res) { + res = new ExternalCall[](6); + for (uint256 i = 0; i < 6; ++i) { + res[i].target = target; + res[i].payload = payloads[i]; + } + } } diff --git a/test/utils/integration-tests.sol b/test/utils/integration-tests.sol new file mode 100644 index 00000000..d5eee8b6 --- /dev/null +++ b/test/utils/integration-tests.sol @@ -0,0 +1,893 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +/* solhint-disable no-console */ + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; + +import {Durations, Duration} from "contracts/types/Duration.sol"; +import {Timestamps, Timestamp} from "contracts/types/Duration.sol"; +import {PercentsD16, PercentD16} from "contracts/types/PercentD16.sol"; + +import {ITimelock} from "contracts/interfaces/ITimelock.sol"; +import {IGovernance} from "contracts/interfaces/IGovernance.sol"; +import {IEmergencyProtectedTimelock} from "contracts/interfaces/IEmergencyProtectedTimelock.sol"; +import {IWithdrawalQueue} from "./interfaces/IWithdrawalQueue.sol"; + +import {IPotentiallyDangerousContract} from "./interfaces/IPotentiallyDangerousContract.sol"; + +import {Proposers} from "contracts/libraries/Proposers.sol"; +import {Status as ProposalStatus} from "contracts/libraries/ExecutableProposals.sol"; + +import {Escrow, ISignallingEscrow, IRageQuitEscrow} from "contracts/Escrow.sol"; +import {DualGovernance, State as DGState} from "contracts/DualGovernance.sol"; +import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; + +import {LidoUtils, IStETH, IWstETH, IWithdrawalQueue} from "./lido-utils.sol"; +import {TargetMock} from "./target-mock.sol"; +import {TestingAssertEqExtender} from "./testing-assert-eq-extender.sol"; +import {ExternalCall, ExternalCallHelpers} from "../utils/executor-calls.sol"; + +import { + ContractsDeployment, + TGSetupDeployConfig, + DualGovernanceConfig, + TGSetupDeployedContracts, + DGSetupDeployConfig, + DGSetupDeployArtifacts, + DGSetupDeployedContracts, + DualGovernanceContractDeployConfig, + TiebreakerContractDeployConfig, + TiebreakerCommitteeDeployConfig, + TimelockContractDeployConfig +} from "scripts/utils/contracts-deployment.sol"; + +uint256 constant MAINNET_CHAIN_ID = 1; +uint256 constant HOLESKY_CHAIN_ID = 17000; + +uint256 constant DEFAULT_HOLESKY_FORK_BLOCK_NUMBER = 3209735; +uint256 constant DEFAULT_MAINNET_FORK_BLOCK_NUMBER = 20218312; +uint256 constant LATEST_FORK_BLOCK_NUMBER = type(uint256).max; + +abstract contract ForkTestSetup is Test { + error UnsupportedChainId(uint256 chainId); + + TargetMock internal _targetMock; + LidoUtils.Context internal _lido; + + function _setupFork(uint256 chainId, uint256 blockNumber) internal { + if (chainId == MAINNET_CHAIN_ID) { + vm.createSelectFork(vm.envString("MAINNET_RPC_URL")); + _lido = LidoUtils.mainnet(); + } else if (chainId == HOLESKY_CHAIN_ID) { + vm.createSelectFork(vm.envString("HOLESKY_RPC_URL")); + _lido = LidoUtils.holesky(); + } else { + revert UnsupportedChainId(chainId); + } + if (blockNumber != LATEST_FORK_BLOCK_NUMBER) { + vm.rollFork(blockNumber); + } + _targetMock = new TargetMock(); + } + + function _getEnvForkBlockNumberOrDefault(uint256 defaultBlockNumber) internal returns (uint256) { + return vm.envOr("FORK_BLOCK_NUMBER", defaultBlockNumber); + } + + // --- + // Assertions + // --- + + function _assertTargetMockCalls(address caller, ExternalCall[] memory calls) internal { + TargetMock.Call[] memory called = _targetMock.getCalls(); + assertEq(called.length, calls.length); + + for (uint256 i = 0; i < calls.length; ++i) { + assertEq(called[i].sender, caller); + assertEq(called[i].value, calls[i].value); + assertEq(called[i].data, calls[i].payload); + assertEq(called[i].blockNumber, block.number); + } + _targetMock.reset(); + } + + function _assertTargetMockCalls(address[] memory senders, ExternalCall[] memory calls) internal { + TargetMock.Call[] memory called = _targetMock.getCalls(); + assertEq(called.length, calls.length); + assertEq(called.length, senders.length); + + for (uint256 i = 0; i < calls.length; ++i) { + assertEq(called[i].sender, senders[i], "Unexpected sender"); + assertEq(called[i].value, calls[i].value, "Unexpected value"); + assertEq(called[i].data, calls[i].payload, "Unexpected payload"); + assertEq(called[i].blockNumber, block.number); + } + _targetMock.reset(); + } + + function _assertNoTargetMockCalls() internal { + assertEq(_targetMock.getCalls().length, 0, "Unexpected target calls count"); + } + + function _wait(Duration duration) internal { + vm.warp(block.timestamp + Duration.unwrap(duration)); + } + + function _step(string memory text) internal { + // solhint-disable-next-line + console.log(string.concat(">>> ", text)); + } +} + +contract GovernedTimelockSetup is ForkTestSetup, TestingAssertEqExtender { + Duration internal immutable _DEFAULT_EMERGENCY_MODE_DURATION = Durations.from(180 days); + Duration internal immutable _DEFAULT_EMERGENCY_PROTECTION_DURATION = Durations.from(90 days); + address internal immutable _DEFAULT_EMERGENCY_ACTIVATION_COMMITTEE = + makeAddr("DEFAULT_EMERGENCY_ACTIVATION_COMMITTEE"); + address internal immutable _DEFAULT_EMERGENCY_EXECUTION_COMMITTEE = + makeAddr("DEFAULT_EMERGENCY_EXECUTION_COMMITTEE"); + + EmergencyProtectedTimelock internal _timelock; + + function _setTimelock(EmergencyProtectedTimelock timelock) internal { + _timelock = timelock; + } + + /// @dev When the emergencyGovernanceProposer is address(0) the emergency protection is considered + /// disabled + function _getDefaultTimelockDeployConfig(address emergencyGovernanceProposer) + internal + view + returns (TimelockContractDeployConfig.Context memory) + { + address emergencyActivationCommittee = + emergencyGovernanceProposer == address(0) ? address(0) : _DEFAULT_EMERGENCY_ACTIVATION_COMMITTEE; + address emergencyExecutionCommittee = + emergencyGovernanceProposer == address(0) ? address(0) : _DEFAULT_EMERGENCY_EXECUTION_COMMITTEE; + Duration emergencyModeDuration = + emergencyGovernanceProposer == address(0) ? Durations.ZERO : _DEFAULT_EMERGENCY_MODE_DURATION; + Timestamp emergencyProtectionEndDate = emergencyGovernanceProposer == address(0) + ? Timestamps.ZERO + : _DEFAULT_EMERGENCY_PROTECTION_DURATION.addTo(Timestamps.now()); + + return TimelockContractDeployConfig.Context({ + afterSubmitDelay: Durations.from(3 days), + afterScheduleDelay: Durations.from(3 days), + sanityCheckParams: EmergencyProtectedTimelock.SanityCheckParams({ + minExecutionDelay: Durations.from(3 days), + maxAfterSubmitDelay: Durations.from(45 days), + maxAfterScheduleDelay: Durations.from(45 days), + maxEmergencyModeDuration: Durations.from(365 days), + maxEmergencyProtectionDuration: Durations.from(365 days) + }), + emergencyGovernanceProposer: emergencyGovernanceProposer, + emergencyActivationCommittee: emergencyActivationCommittee, + emergencyExecutionCommittee: emergencyExecutionCommittee, + emergencyModeDuration: emergencyModeDuration, + emergencyProtectionEndDate: emergencyProtectionEndDate + }); + } + + function _isEmergencyModeActive() internal view returns (bool) { + return _timelock.isEmergencyModeActive(); + } + + function _isEmergencyProtectionEnabled() internal view returns (bool) { + return _timelock.isEmergencyProtectionEnabled(); + } + + function _getAdminExecutor() internal view returns (address) { + return _timelock.getAdminExecutor(); + } + + function _getAfterSubmitDelay() internal view returns (Duration) { + return _timelock.getAfterSubmitDelay(); + } + + function _getAfterScheduleDelay() internal view returns (Duration) { + return _timelock.getAfterScheduleDelay(); + } + + function _getMockTargetRegularStaffCalls() internal view returns (ExternalCall[] memory) { + return _getMockTargetRegularStaffCalls(1); + } + + function _getMockTargetRegularStaffCalls(uint256 callsCount) internal view returns (ExternalCall[] memory calls) { + calls = new ExternalCall[](callsCount); + + for (uint256 i = 0; i < calls.length; ++i) { + calls[i].target = address(_targetMock); + calls[i].payload = abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (i)); + } + } + + function _getEmergencyModeDuration() internal view returns (Duration) { + return _timelock.getEmergencyProtectionDetails().emergencyModeDuration; + } + + function _getEmergencyProtectionDuration() internal view returns (Duration) { + Timestamp emergencyProtectionEndsAfter = _getEmergencyProtectionEndsAfter(); + return emergencyProtectionEndsAfter > Timestamps.now() + ? Durations.from(emergencyProtectionEndsAfter.toSeconds() - Timestamps.now().toSeconds()) + : Durations.ZERO; + } + + function _getEmergencyProtectionEndsAfter() internal view returns (Timestamp) { + return _timelock.getEmergencyProtectionDetails().emergencyProtectionEndsAfter; + } + + function _getEmergencyModeEndsAfter() internal view returns (Timestamp) { + return _timelock.getEmergencyProtectionDetails().emergencyModeEndsAfter; + } + + function _getLastProposalId() internal view returns (uint256) { + return _timelock.getProposalsCount(); + } + + function _executeProposal(uint256 proposalId) internal { + _timelock.execute(proposalId); + } + + function _submitProposal(address proposer, ExternalCall[] memory calls) internal returns (uint256 proposalId) { + proposalId = _submitProposal(proposer, calls, string("")); + } + + function _submitProposal( + address proposer, + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + uint256 proposalsCountBefore = _timelock.getProposalsCount(); + + vm.startPrank(address(proposer)); + IGovernance(_timelock.getGovernance()).submitProposal(calls, metadata); + vm.stopPrank(); + + proposalId = _timelock.getProposalsCount(); + // new call is scheduled but is not executable yet + assertEq(proposalId, proposalsCountBefore + 1); + } + + function _adoptProposal( + address proposer, + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + proposalId = _submitProposal(proposer, calls, metadata); + + _assertProposalSubmitted(proposalId); + _wait(_getAfterSubmitDelay()); + + _scheduleProposal(proposalId); + _assertProposalScheduled(proposalId); + + _wait(_getAfterScheduleDelay()); + _executeProposal(proposalId); + _assertProposalExecuted(proposalId); + } + + function _scheduleProposal(uint256 proposalId) internal { + IGovernance(_timelock.getGovernance()).scheduleProposal(proposalId); + } + + function _activateEmergencyMode() internal { + address emergencyActivationCommittee = _timelock.getEmergencyActivationCommittee(); + if (emergencyActivationCommittee == address(0)) { + revert("Emergency activation committee not set"); + } + vm.prank(emergencyActivationCommittee); + _timelock.activateEmergencyMode(); + + assertTrue(_timelock.isEmergencyModeActive()); + + assertEq(_getEmergencyModeEndsAfter(), _getEmergencyModeDuration().addTo(Timestamps.now())); + } + + function _emergencyReset() internal { + assertTrue(_timelock.isEmergencyModeActive()); + assertNotEq(_timelock.getEmergencyGovernance(), _timelock.getGovernance()); + + vm.prank(_timelock.getEmergencyExecutionCommittee()); + _timelock.emergencyReset(); + + // TODO: assert all emergency protection properties were reset + IEmergencyProtectedTimelock.EmergencyProtectionDetails memory details = + _timelock.getEmergencyProtectionDetails(); + + assertEq(details.emergencyModeDuration, Durations.ZERO); + assertEq(details.emergencyModeEndsAfter, Timestamps.ZERO); + assertEq(details.emergencyProtectionEndsAfter, Timestamps.ZERO); + + assertFalse(_timelock.isEmergencyModeActive()); + assertFalse(_timelock.isEmergencyProtectionEnabled()); + + assertEq(_timelock.getEmergencyActivationCommittee(), address(0)); + assertEq(_timelock.getEmergencyExecutionCommittee(), address(0)); + assertEq(_timelock.getEmergencyGovernance(), _timelock.getGovernance()); + } + + function _emergencyExecute(uint256 proposalId) internal { + assertTrue(_timelock.isEmergencyModeActive()); + + vm.prank(_timelock.getEmergencyExecutionCommittee()); + _timelock.emergencyExecute(proposalId); + + _assertProposalExecuted(proposalId); + } + + // --- + // Assertions + // --- + + function _assertProposalSubmitted(uint256 proposalId) internal { + assertEq( + _timelock.getProposalDetails(proposalId).status, + ProposalStatus.Submitted, + "TimelockProposal not in 'Submitted' state" + ); + } + + function _assertSubmittedProposalData(uint256 proposalId, ExternalCall[] memory calls) internal { + _assertSubmittedProposalData(proposalId, _timelock.getAdminExecutor(), calls); + } + + function _assertSubmittedProposalData(uint256 proposalId, address executor, ExternalCall[] memory calls) internal { + (ITimelock.ProposalDetails memory proposal, ExternalCall[] memory calls) = _timelock.getProposal(proposalId); + assertEq(proposal.id, proposalId, "unexpected proposal id"); + assertEq(proposal.status, ProposalStatus.Submitted, "unexpected status value"); + assertEq(proposal.executor, executor, "unexpected executor"); + assertEq(proposal.submittedAt, Timestamps.now(), "unexpected scheduledAt"); + assertEq(calls.length, calls.length, "unexpected calls length"); + + for (uint256 i = 0; i < calls.length; ++i) { + ExternalCall memory expected = calls[i]; + ExternalCall memory actual = calls[i]; + + assertEq(actual.value, expected.value); + assertEq(actual.target, expected.target); + assertEq(actual.payload, expected.payload); + } + } + + function _assertCanSchedule(uint256 proposalId, bool canSchedule) internal { + assertEq( + IGovernance(_timelock.getGovernance()).canScheduleProposal(proposalId), + canSchedule, + "unexpected canSchedule() value" + ); + } + + function _assertCanExecute(uint256 proposalId, bool canExecute) internal { + assertEq(_timelock.canExecute(proposalId), canExecute, "unexpected canExecute() value"); + } + + function _assertProposalScheduled(uint256 proposalId) internal { + assertEq( + _timelock.getProposalDetails(proposalId).status, + ProposalStatus.Scheduled, + "TimelockProposal not in 'Scheduled' state" + ); + } + + function _assertProposalExecuted(uint256 proposalId) internal { + assertEq( + _timelock.getProposalDetails(proposalId).status, + ProposalStatus.Executed, + "TimelockProposal not in 'Executed' state" + ); + } + + function _assertProposalCancelled(uint256 proposalId) internal { + assertEq( + _timelock.getProposalDetails(proposalId).status, + ProposalStatus.Cancelled, + "Proposal not in 'Canceled' state" + ); + } + + function external__activateEmergencyMode() external { + _activateEmergencyMode(); + } +} + +contract DGScenarioTestSetup is GovernedTimelockSetup { + using LidoUtils for LidoUtils.Context; + + address internal immutable _DEFAULT_RESEAL_COMMITTEE = makeAddr("DEFAULT_RESEAL_COMMITTEE"); + + DGSetupDeployConfig.Context internal _dgDeployConfig; + DGSetupDeployedContracts.Context internal _dgDeployedContracts; + + function _getDefaultDGDeployConfig(address emergencyGovernanceProposer) + internal + returns (DGSetupDeployConfig.Context memory config) + { + uint256 tiebreakerCommitteesCount = 2; + uint256 tiebreakerCommitteeMembersCount = 5; + + TiebreakerCommitteeDeployConfig[] memory tiebreakerCommitteeConfigs = + new TiebreakerCommitteeDeployConfig[](tiebreakerCommitteesCount); + + for (uint256 i = 0; i < tiebreakerCommitteesCount; ++i) { + tiebreakerCommitteeConfigs[i].quorum = tiebreakerCommitteeMembersCount; + tiebreakerCommitteeConfigs[i].members = new address[](tiebreakerCommitteeMembersCount); + for (uint256 j = 0; j < tiebreakerCommitteeMembersCount; ++j) { + tiebreakerCommitteeConfigs[i].members[j] = vm.randomAddress(); + } + } + + address[] memory sealableWithdrawalBlockers = new address[](1); + sealableWithdrawalBlockers[0] = address(_lido.withdrawalQueue); + + config = DGSetupDeployConfig.Context({ + chainId: 1, + tiebreaker: TiebreakerContractDeployConfig.Context({ + quorum: tiebreakerCommitteesCount, + committeesCount: tiebreakerCommitteesCount, + executionDelay: Durations.from(30 days), + committees: tiebreakerCommitteeConfigs + }), + dualGovernanceConfigProvider: DualGovernanceConfig.Context({ + firstSealRageQuitSupport: PercentsD16.fromBasisPoints(3_00), + secondSealRageQuitSupport: PercentsD16.fromBasisPoints(15_00), + // + minAssetsLockDuration: Durations.from(5 hours), + // + vetoSignallingMinDuration: Durations.from(3 days), + vetoSignallingMaxDuration: Durations.from(30 days), + vetoSignallingMinActiveDuration: Durations.from(5 hours), + vetoSignallingDeactivationMaxDuration: Durations.from(5 days), + vetoCooldownDuration: Durations.from(4 days), + // + rageQuitExtensionPeriodDuration: Durations.from(7 days), + rageQuitEthWithdrawalsMinDelay: Durations.from(30 days), + rageQuitEthWithdrawalsMaxDelay: Durations.from(180 days), + rageQuitEthWithdrawalsDelayGrowth: Durations.from(15 days) + }), + dualGovernance: DualGovernanceContractDeployConfig.Context({ + signallingTokens: DualGovernance.SignallingTokens({ + stETH: _lido.stETH, + wstETH: _lido.wstETH, + withdrawalQueue: _lido.withdrawalQueue + }), + sanityCheckParams: DualGovernance.SanityCheckParams({ + minWithdrawalsBatchSize: 4, + minTiebreakerActivationTimeout: Durations.from(90 days), + maxTiebreakerActivationTimeout: Durations.from(730 days), + maxSealableWithdrawalBlockersCount: 255, + maxMinAssetsLockDuration: Durations.from(7 days) + }), + adminProposer: address(_lido.voting), + resealCommittee: _DEFAULT_RESEAL_COMMITTEE, + proposalsCanceller: address(_lido.voting), + tiebreakerActivationTimeout: Durations.from(365 days), + sealableWithdrawalBlockers: sealableWithdrawalBlockers + }), + timelock: _getDefaultTimelockDeployConfig(emergencyGovernanceProposer) + }); + } + + function _deployDGSetup(bool isEmergencyProtectionEnabled) internal { + _setupFork(MAINNET_CHAIN_ID, _getEnvForkBlockNumberOrDefault(DEFAULT_MAINNET_FORK_BLOCK_NUMBER)); + _setDGDeployConfig(_getDefaultDGDeployConfig(isEmergencyProtectionEnabled ? address(_lido.voting) : address(0))); + _dgDeployedContracts = ContractsDeployment.deployDGSetup(address(this), _dgDeployConfig); + + vm.startPrank(address(_lido.agent)); + _lido.withdrawalQueue.grantRole(_lido.withdrawalQueue.PAUSE_ROLE(), address(_dgDeployedContracts.resealManager)); + _lido.withdrawalQueue.grantRole( + _lido.withdrawalQueue.RESUME_ROLE(), address(_dgDeployedContracts.resealManager) + ); + vm.stopPrank(); + + _setTimelock(_dgDeployedContracts.timelock); + _lido.removeStakingLimit(); + } + + function _deployDGSetup(address emergencyGovernanceProposer) internal { + _setupFork(MAINNET_CHAIN_ID, _getEnvForkBlockNumberOrDefault(DEFAULT_MAINNET_FORK_BLOCK_NUMBER)); + _setDGDeployConfig(_getDefaultDGDeployConfig(emergencyGovernanceProposer)); + _dgDeployedContracts = ContractsDeployment.deployDGSetup(address(this), _dgDeployConfig); + + _setTimelock(_dgDeployedContracts.timelock); + _lido.removeStakingLimit(); + } + + function _adoptProposalByAdminProposer( + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + proposalId = _adoptProposal(_getFirstAdminProposer(), calls, metadata); + } + + function _submitProposalByAdminProposer(ExternalCall[] memory calls) internal returns (uint256 proposalId) { + proposalId = _submitProposalByAdminProposer(calls, string("")); + } + + function _submitProposalByAdminProposer( + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + proposalId = _submitProposal(_getFirstAdminProposer(), calls, metadata); + } + + function _getProposers() internal view returns (Proposers.Proposer[] memory) { + return _dgDeployedContracts.dualGovernance.getProposers(); + } + + function _getGovernance() internal view returns (address governance) { + return _timelock.getGovernance(); + } + + function _getFirstAdminProposer() internal view returns (address) { + Proposers.Proposer[] memory proposers = _getProposers(); + + if (proposers.length == 0) { + revert("No available proposers"); + } + + for (uint256 i = 0; i < proposers.length; ++i) { + if (_dgDeployedContracts.dualGovernance.isExecutor(proposers[i].executor)) { + return proposers[i].account; + } + } + } + + function _getSealableWithdrawalBlockers() internal view returns (address[] memory) { + return _dgDeployedContracts.dualGovernance.getTiebreakerDetails().sealableWithdrawalBlockers; + } + + function _getMinAssetsLockDuration() internal view returns (Duration) { + return _getVetoSignallingEscrow().getMinAssetsLockDuration(); + } + + function _getVetoSignallingEscrow() internal view returns (ISignallingEscrow) { + return ISignallingEscrow(payable(address(_dgDeployedContracts.dualGovernance.getVetoSignallingEscrow()))); + } + + function _getRageQuitEscrow() internal view returns (IRageQuitEscrow) { + return IRageQuitEscrow(payable(address(_dgDeployedContracts.dualGovernance.getRageQuitEscrow()))); + } + + function _getSecondSealRageQuitSupport() internal view returns (PercentD16) { + return _dgDeployedContracts.dualGovernanceConfigProvider.SECOND_SEAL_RAGE_QUIT_SUPPORT(); + } + + function _getFirstSealRageQuitSupport() internal view returns (PercentD16) { + return _dgDeployedContracts.dualGovernanceConfigProvider.FIRST_SEAL_RAGE_QUIT_SUPPORT(); + } + + function _getVetoSignallingMaxDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernanceConfigProvider.VETO_SIGNALLING_MAX_DURATION(); + } + + function _getVetoSignallingMinDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernanceConfigProvider.VETO_SIGNALLING_MIN_DURATION(); + } + + function _getVetoSignallingDeactivationMaxDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION(); + } + + function _getVetoCooldownDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernanceConfigProvider.VETO_COOLDOWN_DURATION(); + } + + function _getRageQuitExtensionPeriodDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernanceConfigProvider.RAGE_QUIT_EXTENSION_PERIOD_DURATION(); + } + + function _getRageQuitEthWithdrawalsDelay() internal view returns (Duration) { + return _getRageQuitEscrow().getRageQuitEscrowDetails().rageQuitEthWithdrawalsDelay; + } + + function _getVetoSignallingDuration() internal view returns (Duration) { + return _dgDeployedContracts.dualGovernance.getStateDetails().vetoSignallingDuration; + } + + function _getVetoSignallingActivatedAt() internal view returns (Timestamp) { + return _dgDeployedContracts.dualGovernance.getStateDetails().vetoSignallingActivatedAt; + } + + function _setDGDeployConfig(DGSetupDeployConfig.Context memory config) internal { + _dgDeployConfig.chainId = config.chainId; + _dgDeployConfig.timelock = config.timelock; + _dgDeployConfig.dualGovernance = config.dualGovernance; + _dgDeployConfig.dualGovernanceConfigProvider = config.dualGovernanceConfigProvider; + + _dgDeployConfig.tiebreaker.quorum = config.tiebreaker.quorum; + _dgDeployConfig.tiebreaker.executionDelay = config.tiebreaker.executionDelay; + _dgDeployConfig.tiebreaker.committeesCount = config.tiebreaker.committeesCount; + + // remove previously set committees + for (uint256 i = 0; i < _dgDeployConfig.tiebreaker.committees.length; ++i) { + _dgDeployConfig.tiebreaker.committees.pop(); + } + + for (uint256 i = 0; i < config.tiebreaker.committees.length; ++i) { + _dgDeployConfig.tiebreaker.committees.push(config.tiebreaker.committees[i]); + } + } + + function _grantAragonAgentExecuteRole(address grantee) internal { + if (!_lido.hasPermission(grantee, address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE())) { + _lido.grantPermission(address(_lido.agent), _lido.agent.RUN_SCRIPT_ROLE(), grantee); + } + + if (!_lido.hasPermission(grantee, address(_lido.agent), _lido.agent.EXECUTE_ROLE())) { + _lido.grantPermission(address(_lido.agent), _lido.agent.EXECUTE_ROLE(), grantee); + } + } + + function _activateNextState() internal { + _dgDeployedContracts.dualGovernance.activateNextState(); + } + + // --- + // Balances Manipulation + // --- + + function _setupStETHBalance(address account, uint256 amount) internal { + _lido.submitStETH(account, amount); + } + + function _setupStETHBalance(address account, PercentD16 tvlPercentage) internal { + _lido.submitStETH(account, _lido.calcAmountToDepositFromPercentageOfTVL(tvlPercentage)); + } + + function _setupWstETHBalance(address account, uint256 amount) internal { + _lido.submitWstETH(account, amount); + } + + function _setupWstETHBalance(address account, PercentD16 tvlPercentage) internal { + _lido.submitWstETH(account, _lido.calcSharesToDepositFromPercentageOfTVL(tvlPercentage)); + } + + // --- + // Withdrawal Queue Operations + // --- + function _finalizeWithdrawalQueue() internal { + _lido.finalizeWithdrawalQueue(); + } + + function _finalizeWithdrawalQueue(uint256 id) internal { + _lido.finalizeWithdrawalQueue(id); + } + + function _simulateRebase(PercentD16 rebaseFactor) internal { + _lido.simulateRebase(rebaseFactor); + } + + // --- + // Escrow Manipulation + // --- + function _lockStETH(address vetoer, PercentD16 tvlPercentage) internal { + _lockStETH(vetoer, _lido.calcAmountFromPercentageOfTVL(tvlPercentage)); + } + + function _lockStETH(address vetoer, uint256 amount) internal { + ISignallingEscrow escrow = _getVetoSignallingEscrow(); + vm.startPrank(vetoer); + if (_lido.stETH.allowance(vetoer, address(escrow)) < amount) { + _lido.stETH.approve(address(escrow), amount); + } + escrow.lockStETH(amount); + vm.stopPrank(); + } + + function _unlockStETH(address vetoer) internal { + vm.startPrank(vetoer); + _getVetoSignallingEscrow().unlockStETH(); + vm.stopPrank(); + } + + function _lockWstETH(address vetoer, PercentD16 tvlPercentage) internal { + _lockWstETH(vetoer, _lido.calcSharesFromPercentageOfTVL(tvlPercentage)); + } + + function _lockWstETH(address vetoer, uint256 amount) internal { + ISignallingEscrow escrow = _getVetoSignallingEscrow(); + vm.startPrank(vetoer); + if (_lido.wstETH.allowance(vetoer, address(escrow)) < amount) { + _lido.wstETH.approve(address(escrow), amount); + } + escrow.lockWstETH(amount); + vm.stopPrank(); + } + + function _unlockWstETH(address vetoer) internal { + ISignallingEscrow escrow = _getVetoSignallingEscrow(); + uint256 wstETHBalanceBefore = _lido.wstETH.balanceOf(vetoer); + ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); + + vm.startPrank(vetoer); + uint256 wstETHUnlocked = escrow.unlockWstETH(); + vm.stopPrank(); + + // 1 wei rounding issue may arise because of the wrapping stETH into wstETH before + // sending funds to the user + assertApproxEqAbs(wstETHUnlocked, vetoerDetailsBefore.stETHLockedShares.toUint256(), 1); + assertApproxEqAbs( + _lido.wstETH.balanceOf(vetoer), wstETHBalanceBefore + vetoerDetailsBefore.stETHLockedShares.toUint256(), 1 + ); + } + + function _lockUnstETH(address vetoer, uint256[] memory unstETHIds) internal { + ISignallingEscrow escrow = _getVetoSignallingEscrow(); + ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); + ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsBefore = + escrow.getSignallingEscrowDetails(); + + uint256 unstETHTotalSharesLocked = 0; + IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = + _lido.withdrawalQueue.getWithdrawalStatus(unstETHIds); + for (uint256 i = 0; i < unstETHIds.length; ++i) { + unstETHTotalSharesLocked += statuses[i].amountOfShares; + } + + vm.startPrank(vetoer); + _lido.withdrawalQueue.setApprovalForAll(address(escrow), true); + escrow.lockUnstETH(unstETHIds); + _lido.withdrawalQueue.setApprovalForAll(address(escrow), false); + vm.stopPrank(); + + for (uint256 i = 0; i < unstETHIds.length; ++i) { + assertEq(_lido.withdrawalQueue.ownerOf(unstETHIds[i]), address(escrow)); + } + + ISignallingEscrow.VetoerDetails memory vetoerDetailsAfter = escrow.getVetoerDetails(vetoer); + assertEq(vetoerDetailsAfter.unstETHIdsCount, vetoerDetailsBefore.unstETHIdsCount + unstETHIds.length); + + ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsAfter = + escrow.getSignallingEscrowDetails(); + assertEq( + signallingEscrowDetailsAfter.totalUnstETHUnfinalizedShares.toUint256(), + signallingEscrowDetailsBefore.totalUnstETHUnfinalizedShares.toUint256() + unstETHTotalSharesLocked + ); + } + + function _unlockUnstETH(address vetoer, uint256[] memory unstETHIds) internal { + ISignallingEscrow escrow = _getVetoSignallingEscrow(); + ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); + ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsBefore = + escrow.getSignallingEscrowDetails(); + + uint256 unstETHTotalSharesUnlocked = 0; + IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = + _lido.withdrawalQueue.getWithdrawalStatus(unstETHIds); + for (uint256 i = 0; i < unstETHIds.length; ++i) { + unstETHTotalSharesUnlocked += statuses[i].amountOfShares; + } + + vm.startPrank(vetoer); + escrow.unlockUnstETH(unstETHIds); + vm.stopPrank(); + + for (uint256 i = 0; i < unstETHIds.length; ++i) { + assertEq(_lido.withdrawalQueue.ownerOf(unstETHIds[i]), vetoer); + } + + ISignallingEscrow.VetoerDetails memory vetoerDetailsAfter = escrow.getVetoerDetails(vetoer); + assertEq(vetoerDetailsAfter.unstETHIdsCount, vetoerDetailsBefore.unstETHIdsCount - unstETHIds.length); + + // TODO: implement correct assert. It must consider was unstETH finalized or not + ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsAfter = + escrow.getSignallingEscrowDetails(); + assertEq( + signallingEscrowDetailsAfter.totalUnstETHUnfinalizedShares.toUint256(), + signallingEscrowDetailsBefore.totalUnstETHUnfinalizedShares.toUint256() - unstETHTotalSharesUnlocked + ); + } + + function _assertNormalState() internal { + assertEq(_dgDeployedContracts.dualGovernance.getPersistedState(), DGState.Normal); + } + + function _assertVetoSignalingState() internal { + assertEq(_dgDeployedContracts.dualGovernance.getPersistedState(), DGState.VetoSignalling); + } + + function _assertRageQuitState() internal { + assertEq(_dgDeployedContracts.dualGovernance.getPersistedState(), DGState.RageQuit); + } + + function _assertVetoSignallingDeactivationState() internal { + assertEq(_dgDeployedContracts.dualGovernance.getPersistedState(), DGState.VetoSignallingDeactivation); + } + + function _assertVetoCooldownState() internal { + assertEq(_dgDeployedContracts.dualGovernance.getPersistedState(), DGState.VetoCooldown); + } + + function external__scheduleProposal(uint256 proposalId) external { + _scheduleProposal(proposalId); + } +} + +contract DGRegressionTestSetup is DGScenarioTestSetup { + using LidoUtils for LidoUtils.Context; + + function _loadOrDeployDGSetup() internal returns (bool isSetupLoaded) { + string memory deployArtifactFileName = vm.envOr("DEPLOY_ARTIFACT_FILE_NAME", string("")); + + console.log("File Name:", deployArtifactFileName); + + if (bytes(deployArtifactFileName).length > 0) { + _loadDGSetup(deployArtifactFileName); + console.log("Running on the loaded setup from file '%s'", deployArtifactFileName); + return true; + } + _deployDGSetup({isEmergencyProtectionEnabled: true}); + console.log("Running on the deployed setup"); + return false; + } + + function _loadDGSetup(string memory deployArtifactFileName) internal { + DGSetupDeployArtifacts.Context memory deployArtifacts = DGSetupDeployArtifacts.load(deployArtifactFileName); + + console.log("CHAIN ID:", deployArtifacts.deployConfig.chainId); + _setupFork(deployArtifacts.deployConfig.chainId, _getEnvForkBlockNumberOrDefault(LATEST_FORK_BLOCK_NUMBER)); + + _setDGDeployConfig(deployArtifacts.deployConfig); + _dgDeployedContracts = deployArtifacts.deployedContracts; + + _setTimelock(_dgDeployedContracts.timelock); + + _lido.stETH = IStETH(payable(address(_dgDeployConfig.dualGovernance.signallingTokens.stETH))); + _lido.wstETH = IWstETH(address(_dgDeployConfig.dualGovernance.signallingTokens.wstETH)); + _lido.withdrawalQueue = + IWithdrawalQueue(payable(address(_dgDeployConfig.dualGovernance.signallingTokens.withdrawalQueue))); + + _lido.removeStakingLimit(); + } +} + +contract TGScenarioTestSetup is GovernedTimelockSetup { + using LidoUtils for LidoUtils.Context; + + TGSetupDeployConfig.Context internal _tgDeployConfig; + TGSetupDeployedContracts.Context internal _tgDeployedContracts; + + function _getDefaultTGDeployConfig(bool isEmergencyProtectionEnabled) + internal + returns (TGSetupDeployConfig.Context memory) + { + return TGSetupDeployConfig.Context({ + chainId: block.chainid, + governance: address(_lido.voting), + timelock: _getDefaultTimelockDeployConfig(isEmergencyProtectionEnabled ? address(_lido.voting) : address(0)) + }); + } + + function _setTGDeployConfig(TGSetupDeployConfig.Context memory deployConfig) internal { + _tgDeployConfig = deployConfig; + } + + function _deployTGSetup(bool isEmergencyProtectionEnabled) internal { + _setupFork(MAINNET_CHAIN_ID, DEFAULT_MAINNET_FORK_BLOCK_NUMBER); + _setTGDeployConfig(_getDefaultTGDeployConfig(isEmergencyProtectionEnabled)); + _tgDeployedContracts = ContractsDeployment.deployTGSetup(address(this), _tgDeployConfig); + + _setTimelock(_tgDeployedContracts.timelock); + _lido.removeStakingLimit(); + } + + function _submitProposal(ExternalCall[] memory calls) internal returns (uint256 proposalId) { + proposalId = _submitProposal(calls, string("")); + } + + function _submitProposal( + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + proposalId = _submitProposal(address(_tgDeployedContracts.timelockedGovernance.GOVERNANCE()), calls, metadata); + } + + function _adoptProposal( + ExternalCall[] memory calls, + string memory metadata + ) internal returns (uint256 proposalId) { + proposalId = _adoptProposal(address(_tgDeployedContracts.timelockedGovernance.GOVERNANCE()), calls, metadata); + } +} diff --git a/test/utils/interfaces/IAragonAgent.sol b/test/utils/interfaces/IAragonAgent.sol index 11d8642a..0021250b 100644 --- a/test/utils/interfaces/IAragonAgent.sol +++ b/test/utils/interfaces/IAragonAgent.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import {IAragonForwarder} from "./IAragonForwarder.sol"; interface IAragonAgent is IAragonForwarder { + function execute(address _target, uint256 _ethValue, bytes memory _data) external; function EXECUTE_ROLE() external pure returns (bytes32); function RUN_SCRIPT_ROLE() external pure returns (bytes32); } diff --git a/test/utils/interfaces/ISealable.sol b/test/utils/interfaces/ISealable.sol new file mode 100644 index 00000000..acfb76a8 --- /dev/null +++ b/test/utils/interfaces/ISealable.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import {ISealable as ISealableBase} from "contracts/interfaces/ISealable.sol"; + +interface ISealable is ISealableBase { + function PAUSE_ROLE() external view returns (bytes32); + function RESUME_ROLE() external view returns (bytes32); + + function PAUSE_INFINITELY() external view returns (uint256); + + function isPaused() external returns (bool); + function pauseFor(uint256 duration) external; + + function grantRole(bytes32 role, address account) external; +} diff --git a/test/utils/lido-utils.sol b/test/utils/lido-utils.sol index 9f3f42c0..3ba48f1a 100644 --- a/test/utils/lido-utils.sol +++ b/test/utils/lido-utils.sol @@ -18,19 +18,38 @@ import {IAragonForwarder} from "./interfaces/IAragonForwarder.sol"; import {EvmScriptUtils} from "./evm-script-utils.sol"; -import { - ST_ETH, - WST_ETH, - WITHDRAWAL_QUEUE, - DAO_ACL, - LDO_TOKEN, - DAO_AGENT, - DAO_VOTING, - DAO_TOKEN_MANAGER -} from "addresses/mainnet-addresses.sol"; +import {StETHMock} from "../mocks/StETHMock.sol"; uint256 constant ST_ETH_TRANSFERS_SHARE_LOSS_COMPENSATION = 8; // TODO: evaluate min enough value +// --- +// Mainnet Addresses +// --- + +address constant MAINNET_ST_ETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; +address constant MAINNET_WST_ETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; +address constant MAINNET_WITHDRAWAL_QUEUE = 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1; + +address constant MAINNET_DAO_ACL = 0x9895F0F17cc1d1891b6f18ee0b483B6f221b37Bb; +address constant MAINNET_LDO_TOKEN = 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32; +address constant MAINNET_DAO_AGENT = 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c; +address constant MAINNET_DAO_VOTING = 0x2e59A20f205bB85a89C53f1936454680651E618e; +address constant MAINNET_DAO_TOKEN_MANAGER = 0xf73a1260d222f447210581DDf212D915c09a3249; + +// --- +// Holesky Addresses +// --- + +address constant HOLESKY_ST_ETH = 0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034; +address constant HOLESKY_WST_ETH = 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D; +address constant HOLESKY_WITHDRAWAL_QUEUE = 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50; + +address constant HOLESKY_DAO_ACL = 0xfd1E42595CeC3E83239bf8dFc535250e7F48E0bC; +address constant HOLESKY_LDO_TOKEN = 0x14ae7daeecdf57034f3E9db8564e46Dba8D97344; +address constant HOLESKY_DAO_AGENT = 0xE92329EC7ddB11D25e25b3c21eeBf11f15eB325d; +address constant HOLESKY_DAO_VOTING = 0xdA7d2573Df555002503F29aA4003e398d28cc00f; +address constant HOLESKY_DAO_TOKEN_MANAGER = 0xFaa1692c6eea8eeF534e7819749aD93a1420379A; + library LidoUtils { struct Context { // core @@ -50,15 +69,27 @@ library LidoUtils { address internal constant DEFAULT_LDO_WHALE = address(0x1D0_1D0_1D0_1D0_1d0_1D0_1D0_1D0_1D0_1d0_1d0_1d0_1D0_1); function mainnet() internal pure returns (Context memory ctx) { - ctx.stETH = IStETH(ST_ETH); - ctx.wstETH = IWstETH(WST_ETH); - ctx.withdrawalQueue = IWithdrawalQueue(WITHDRAWAL_QUEUE); - - ctx.acl = IAragonACL(DAO_ACL); - ctx.agent = IAragonAgent(DAO_AGENT); - ctx.voting = IAragonVoting(DAO_VOTING); - ctx.ldoToken = IERC20(LDO_TOKEN); - ctx.tokenManager = IAragonForwarder(DAO_TOKEN_MANAGER); + ctx.stETH = IStETH(MAINNET_ST_ETH); + ctx.wstETH = IWstETH(MAINNET_WST_ETH); + ctx.withdrawalQueue = IWithdrawalQueue(MAINNET_WITHDRAWAL_QUEUE); + + ctx.acl = IAragonACL(MAINNET_DAO_ACL); + ctx.agent = IAragonAgent(MAINNET_DAO_AGENT); + ctx.voting = IAragonVoting(MAINNET_DAO_VOTING); + ctx.ldoToken = IERC20(MAINNET_LDO_TOKEN); + ctx.tokenManager = IAragonForwarder(MAINNET_DAO_TOKEN_MANAGER); + } + + function holesky() internal pure returns (Context memory ctx) { + ctx.stETH = IStETH(HOLESKY_ST_ETH); + ctx.wstETH = IWstETH(HOLESKY_WST_ETH); + ctx.withdrawalQueue = IWithdrawalQueue(HOLESKY_WITHDRAWAL_QUEUE); + + ctx.acl = IAragonACL(HOLESKY_DAO_ACL); + ctx.agent = IAragonAgent(HOLESKY_DAO_AGENT); + ctx.voting = IAragonVoting(HOLESKY_DAO_VOTING); + ctx.ldoToken = IERC20(HOLESKY_LDO_TOKEN); + ctx.tokenManager = IAragonForwarder(HOLESKY_DAO_TOKEN_MANAGER); } function calcAmountFromPercentageOfTVL( @@ -194,6 +225,15 @@ library LidoUtils { // ACL // --- + function hasPermission( + Context memory self, + address entity, + address app, + bytes32 role + ) internal view returns (bool) { + return self.acl.hasPermission(entity, app, role); + } + function grantPermission(Context memory self, address app, bytes32 role, address grantee) internal { if (!self.acl.hasPermission(grantee, app, role)) { address manager = self.acl.getPermissionManager(app, role); @@ -253,6 +293,21 @@ library LidoUtils { supportVoteAndWaitTillDecided(self, voteId, DEFAULT_LDO_WHALE); } + function adoptVotePreparedBytecode( + Context memory self, + bytes memory voteScript + ) internal returns (uint256 voteId) { + if (self.ldoToken.balanceOf(DEFAULT_LDO_WHALE) < self.voting.minAcceptQuorumPct()) { + setupLDOWhale(self, DEFAULT_LDO_WHALE); + } + vm.prank(DEFAULT_LDO_WHALE); + self.tokenManager.forward(voteScript); + + voteId = self.voting.votesLength() - 1; + + supportVoteAndWaitTillDecided(self, voteId, DEFAULT_LDO_WHALE); + } + function executeVote(Context memory self, uint256 voteId) internal { self.voting.executeVote(voteId); } diff --git a/test/utils/scenario-test-blueprint.sol b/test/utils/scenario-test-blueprint.sol deleted file mode 100644 index 496876e2..00000000 --- a/test/utils/scenario-test-blueprint.sol +++ /dev/null @@ -1,602 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import {console} from "forge-std/Test.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; - -// --- -// Types -// --- - -import {PercentD16} from "contracts/types/PercentD16.sol"; -import {Duration, Durations} from "contracts/types/Duration.sol"; -import {Timestamp, Timestamps} from "contracts/types/Timestamp.sol"; - -import {ISignallingEscrow} from "contracts/interfaces/ISignallingEscrow.sol"; -import {Escrow} from "contracts/Escrow.sol"; - -// --- -// Interfaces -// --- - -import {IDualGovernance} from "contracts/interfaces/IDualGovernance.sol"; -import {ITimelock} from "contracts/interfaces/ITimelock.sol"; -import {IWithdrawalQueue} from "contracts/interfaces/IWithdrawalQueue.sol"; -import {IPotentiallyDangerousContract} from "./interfaces/IPotentiallyDangerousContract.sol"; - -// --- -// Libraries -// --- - -import {Status as ProposalStatus} from "contracts/libraries/ExecutableProposals.sol"; - -// --- -// Main Contracts -// --- - -import {ExternalCall} from "contracts/libraries/ExternalCalls.sol"; -import {EmergencyProtectedTimelock} from "contracts/EmergencyProtectedTimelock.sol"; -import {IGovernance} from "contracts/TimelockedGovernance.sol"; -import {State as DGState, DualGovernanceStateMachine} from "contracts/DualGovernance.sol"; - -// --- -// Test Utils -// --- - -import {TargetMock} from "../utils/target-mock.sol"; - -import {Random} from "../utils/random.sol"; -import {ExternalCallHelpers} from "../utils/executor-calls.sol"; - -import {LidoUtils, EvmScriptUtils} from "./lido-utils.sol"; - -import {EvmScriptUtils} from "../utils/evm-script-utils.sol"; - -import {SetupDeployment} from "./SetupDeployment.sol"; -import {TestingAssertEqExtender} from "./testing-assert-eq-extender.sol"; - -contract ScenarioTestBlueprint is TestingAssertEqExtender, SetupDeployment { - using LidoUtils for LidoUtils.Context; - - constructor() SetupDeployment(LidoUtils.mainnet(), Random.create(block.timestamp)) { - /// Maybe not the best idea to do it in the constructor, consider move it into setUp method - vm.createSelectFork(vm.envString("MAINNET_RPC_URL")); - vm.rollFork(FORK_BLOCK_NUMBER); - _lido.removeStakingLimit(); - } - - // --- - // Helper Getters - // --- - - function _getAdminExecutor() internal view returns (address) { - return _timelock.getAdminExecutor(); - } - - function _getVetoSignallingEscrow() internal view returns (Escrow) { - return Escrow(payable(_dualGovernance.getVetoSignallingEscrow())); - } - - function _getRageQuitEscrow() internal view returns (Escrow) { - address rageQuitEscrow = _dualGovernance.getRageQuitEscrow(); - return Escrow(payable(rageQuitEscrow)); - } - - function _getMockTargetRegularStaffCalls() internal view returns (ExternalCall[] memory) { - return ExternalCallHelpers.create( - address(_targetMock), abi.encodeCall(IPotentiallyDangerousContract.doRegularStaff, (42)) - ); - } - - function _getVetoSignallingState() - internal - view - returns (bool isActive, uint256 duration, uint256 activatedAt, uint256 enteredAt) - { - IDualGovernance.StateDetails memory stateContext = _dualGovernance.getStateDetails(); - isActive = stateContext.persistedState == DGState.VetoSignalling; - duration = _dualGovernance.getStateDetails().vetoSignallingDuration.toSeconds(); - enteredAt = stateContext.persistedStateEnteredAt.toSeconds(); - activatedAt = stateContext.vetoSignallingActivatedAt.toSeconds(); - } - - function _getVetoSignallingDeactivationState() - internal - view - returns (bool isActive, uint256 duration, uint256 enteredAt) - { - IDualGovernance.StateDetails memory stateContext = _dualGovernance.getStateDetails(); - isActive = stateContext.persistedState == DGState.VetoSignallingDeactivation; - duration = _dualGovernanceConfigProvider.VETO_SIGNALLING_DEACTIVATION_MAX_DURATION().toSeconds(); - enteredAt = stateContext.persistedStateEnteredAt.toSeconds(); - } - - // --- - // Balances Manipulation - // --- - - function _setupStETHBalance(address account, uint256 amount) internal { - _lido.submitStETH(account, amount); - } - - function _setupStETHBalance(address account, PercentD16 tvlPercentage) internal { - _lido.submitStETH(account, _lido.calcAmountToDepositFromPercentageOfTVL(tvlPercentage)); - } - - function _setupWstETHBalance(address account, uint256 amount) internal { - _lido.submitWstETH(account, amount); - } - - function _setupWstETHBalance(address account, PercentD16 tvlPercentage) internal { - _lido.submitWstETH(account, _lido.calcSharesToDepositFromPercentageOfTVL(tvlPercentage)); - } - - function _getBalances(address vetoer) internal view returns (Balances memory balances) { - uint256 stETHAmount = _lido.stETH.balanceOf(vetoer); - uint256 wstETHShares = _lido.wstETH.balanceOf(vetoer); - balances = Balances({ - stETHAmount: stETHAmount, - stETHShares: _lido.stETH.getSharesByPooledEth(stETHAmount), - wstETHAmount: _lido.stETH.getPooledEthByShares(wstETHShares), - wstETHShares: wstETHShares - }); - } - - // --- - // Withdrawal Queue Operations - // --- - function _finalizeWithdrawalQueue() internal { - _lido.finalizeWithdrawalQueue(); - } - - function _finalizeWithdrawalQueue(uint256 id) internal { - _lido.finalizeWithdrawalQueue(id); - } - - function _simulateRebase(PercentD16 rebaseFactor) internal { - _lido.simulateRebase(rebaseFactor); - } - - // --- - // Escrow Manipulation - // --- - function _lockStETH(address vetoer, PercentD16 tvlPercentage) internal { - _lockStETH(vetoer, _lido.calcAmountFromPercentageOfTVL(tvlPercentage)); - } - - function _lockStETH(address vetoer, uint256 amount) internal { - Escrow escrow = _getVetoSignallingEscrow(); - vm.startPrank(vetoer); - if (_lido.stETH.allowance(vetoer, address(escrow)) < amount) { - _lido.stETH.approve(address(escrow), amount); - } - escrow.lockStETH(amount); - vm.stopPrank(); - } - - function _unlockStETH(address vetoer) internal { - vm.startPrank(vetoer); - _getVetoSignallingEscrow().unlockStETH(); - vm.stopPrank(); - } - - function _lockWstETH(address vetoer, PercentD16 tvlPercentage) internal { - _lockWstETH(vetoer, _lido.calcSharesFromPercentageOfTVL(tvlPercentage)); - } - - function _lockWstETH(address vetoer, uint256 amount) internal { - Escrow escrow = _getVetoSignallingEscrow(); - vm.startPrank(vetoer); - if (_lido.wstETH.allowance(vetoer, address(escrow)) < amount) { - _lido.wstETH.approve(address(escrow), amount); - } - escrow.lockWstETH(amount); - vm.stopPrank(); - } - - function _unlockWstETH(address vetoer) internal { - Escrow escrow = _getVetoSignallingEscrow(); - uint256 wstETHBalanceBefore = _lido.wstETH.balanceOf(vetoer); - ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); - - vm.startPrank(vetoer); - uint256 wstETHUnlocked = escrow.unlockWstETH(); - vm.stopPrank(); - - // 1 wei rounding issue may arise because of the wrapping stETH into wstETH before - // sending funds to the user - assertApproxEqAbs(wstETHUnlocked, vetoerDetailsBefore.stETHLockedShares.toUint256(), 1); - assertApproxEqAbs( - _lido.wstETH.balanceOf(vetoer), wstETHBalanceBefore + vetoerDetailsBefore.stETHLockedShares.toUint256(), 1 - ); - } - - function _lockUnstETH(address vetoer, uint256[] memory unstETHIds) internal { - Escrow escrow = _getVetoSignallingEscrow(); - ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); - ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsBefore = - escrow.getSignallingEscrowDetails(); - - uint256 unstETHTotalSharesLocked = 0; - IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = - _lido.withdrawalQueue.getWithdrawalStatus(unstETHIds); - for (uint256 i = 0; i < unstETHIds.length; ++i) { - unstETHTotalSharesLocked += statuses[i].amountOfShares; - } - - vm.startPrank(vetoer); - _lido.withdrawalQueue.setApprovalForAll(address(escrow), true); - escrow.lockUnstETH(unstETHIds); - _lido.withdrawalQueue.setApprovalForAll(address(escrow), false); - vm.stopPrank(); - - for (uint256 i = 0; i < unstETHIds.length; ++i) { - assertEq(_lido.withdrawalQueue.ownerOf(unstETHIds[i]), address(escrow)); - } - - ISignallingEscrow.VetoerDetails memory vetoerDetailsAfter = escrow.getVetoerDetails(vetoer); - assertEq(vetoerDetailsAfter.unstETHIdsCount, vetoerDetailsBefore.unstETHIdsCount + unstETHIds.length); - - ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsAfter = - escrow.getSignallingEscrowDetails(); - assertEq( - signallingEscrowDetailsAfter.totalUnstETHUnfinalizedShares.toUint256(), - signallingEscrowDetailsBefore.totalUnstETHUnfinalizedShares.toUint256() + unstETHTotalSharesLocked - ); - } - - function _unlockUnstETH(address vetoer, uint256[] memory unstETHIds) internal { - Escrow escrow = _getVetoSignallingEscrow(); - ISignallingEscrow.VetoerDetails memory vetoerDetailsBefore = escrow.getVetoerDetails(vetoer); - ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsBefore = - escrow.getSignallingEscrowDetails(); - - uint256 unstETHTotalSharesUnlocked = 0; - IWithdrawalQueue.WithdrawalRequestStatus[] memory statuses = - _lido.withdrawalQueue.getWithdrawalStatus(unstETHIds); - for (uint256 i = 0; i < unstETHIds.length; ++i) { - unstETHTotalSharesUnlocked += statuses[i].amountOfShares; - } - - vm.startPrank(vetoer); - escrow.unlockUnstETH(unstETHIds); - vm.stopPrank(); - - for (uint256 i = 0; i < unstETHIds.length; ++i) { - assertEq(_lido.withdrawalQueue.ownerOf(unstETHIds[i]), vetoer); - } - - ISignallingEscrow.VetoerDetails memory vetoerDetailsAfter = escrow.getVetoerDetails(vetoer); - assertEq(vetoerDetailsAfter.unstETHIdsCount, vetoerDetailsBefore.unstETHIdsCount - unstETHIds.length); - - // TODO: implement correct assert. It must consider was unstETH finalized or not - ISignallingEscrow.SignallingEscrowDetails memory signallingEscrowDetailsAfter = - escrow.getSignallingEscrowDetails(); - assertEq( - signallingEscrowDetailsAfter.totalUnstETHUnfinalizedShares.toUint256(), - signallingEscrowDetailsBefore.totalUnstETHUnfinalizedShares.toUint256() - unstETHTotalSharesUnlocked - ); - } - - // --- - // Dual Governance State Manipulation - // --- - function _activateNextState() internal { - _dualGovernance.activateNextState(); - } - - // --- - // Proposals Submission - // --- - function _submitProposalViaDualGovernance( - string memory description, - ExternalCall[] memory calls - ) internal returns (uint256 proposalId) { - proposalId = _submitProposal(_dualGovernance, description, calls); - } - - function _submitProposalViaTimelockedGovernance( - string memory description, - ExternalCall[] memory calls - ) internal returns (uint256 proposalId) { - proposalId = _submitProposal(_timelockedGovernance, description, calls); - } - - function _submitProposal( - IGovernance governance, - string memory description, - ExternalCall[] memory calls - ) internal returns (uint256 proposalId) { - uint256 proposalsCountBefore = _timelock.getProposalsCount(); - - bytes memory script = EvmScriptUtils.encodeEvmCallScript( - address(governance), abi.encodeCall(IGovernance.submitProposal, (calls, string(""))) - ); - uint256 voteId = _lido.adoptVote(description, script); - - // The scheduled calls count is the same until the vote is enacted - assertEq(_timelock.getProposalsCount(), proposalsCountBefore); - - // executing the vote - _lido.executeVote(voteId); - - proposalId = _timelock.getProposalsCount(); - // new call is scheduled but has not executable yet - assertEq(proposalId, proposalsCountBefore + 1); - } - - function _scheduleProposalViaDualGovernance(uint256 proposalId) internal { - _scheduleProposal(_dualGovernance, proposalId); - } - - function _scheduleProposalViaTimelockedGovernance(uint256 proposalId) internal { - _scheduleProposal(_timelockedGovernance, proposalId); - } - - function _scheduleProposal(IGovernance governance, uint256 proposalId) internal { - governance.scheduleProposal(proposalId); - } - - function _executeProposal(uint256 proposalId) internal { - _timelock.execute(proposalId); - } - - function _scheduleAndExecuteProposal(IGovernance governance, uint256 proposalId) internal { - _scheduleProposal(governance, proposalId); - _executeProposal(proposalId); - } - - // --- - // Assertions - // --- - - function _assertSubmittedProposalData(uint256 proposalId, ExternalCall[] memory calls) internal { - _assertSubmittedProposalData(proposalId, _timelock.getAdminExecutor(), calls); - } - - function _assertSubmittedProposalData(uint256 proposalId, address executor, ExternalCall[] memory calls) internal { - (ITimelock.ProposalDetails memory proposal, ExternalCall[] memory calls) = _timelock.getProposal(proposalId); - assertEq(proposal.id, proposalId, "unexpected proposal id"); - assertEq(proposal.status, ProposalStatus.Submitted, "unexpected status value"); - assertEq(proposal.executor, executor, "unexpected executor"); - assertEq(Timestamp.unwrap(proposal.submittedAt), block.timestamp, "unexpected scheduledAt"); - assertEq(calls.length, calls.length, "unexpected calls length"); - - for (uint256 i = 0; i < calls.length; ++i) { - ExternalCall memory expected = calls[i]; - ExternalCall memory actual = calls[i]; - - assertEq(actual.value, expected.value); - assertEq(actual.target, expected.target); - assertEq(actual.payload, expected.payload); - } - } - - function _assertTargetMockCalls(address sender, ExternalCall[] memory calls) internal { - TargetMock.Call[] memory called = _targetMock.getCalls(); - assertEq(called.length, calls.length); - - for (uint256 i = 0; i < calls.length; ++i) { - assertEq(called[i].sender, sender); - assertEq(called[i].value, calls[i].value); - assertEq(called[i].data, calls[i].payload); - assertEq(called[i].blockNumber, block.number); - } - _targetMock.reset(); - } - - function _assertTargetMockCalls(address[] memory senders, ExternalCall[] memory calls) internal { - TargetMock.Call[] memory called = _targetMock.getCalls(); - assertEq(called.length, calls.length); - assertEq(called.length, senders.length); - - for (uint256 i = 0; i < calls.length; ++i) { - assertEq(called[i].sender, senders[i], "Unexpected sender"); - assertEq(called[i].value, calls[i].value, "Unexpected value"); - assertEq(called[i].data, calls[i].payload, "Unexpected payload"); - assertEq(called[i].blockNumber, block.number); - } - _targetMock.reset(); - } - - function _assertCanExecute(uint256 proposalId, bool canExecute) internal { - assertEq(_timelock.canExecute(proposalId), canExecute, "unexpected canExecute() value"); - } - - function _assertCanScheduleViaDualGovernance(uint256 proposalId, bool canSchedule) internal { - _assertCanSchedule(_dualGovernance, proposalId, canSchedule); - } - - function _assertCanScheduleViaTimelockedGovernance(uint256 proposalId, bool canSchedule) internal { - _assertCanSchedule(_timelockedGovernance, proposalId, canSchedule); - } - - function _assertCanSchedule(IGovernance governance, uint256 proposalId, bool canSchedule) internal { - assertEq(governance.canScheduleProposal(proposalId), canSchedule, "unexpected canSchedule() value"); - } - - function _assertCanScheduleAndExecute(IGovernance governance, uint256 proposalId) internal { - _assertCanSchedule(governance, proposalId, true); - assertFalse( - _timelock.isEmergencyProtectionEnabled(), - "Execution in the same block with scheduling allowed only when emergency protection is disabled" - ); - } - - function _assertProposalSubmitted(uint256 proposalId) internal { - assertEq( - _timelock.getProposalDetails(proposalId).status, - ProposalStatus.Submitted, - "TimelockProposal not in 'Submitted' state" - ); - } - - function _assertProposalScheduled(uint256 proposalId) internal { - assertEq( - _timelock.getProposalDetails(proposalId).status, - ProposalStatus.Scheduled, - "TimelockProposal not in 'Scheduled' state" - ); - } - - function _assertProposalExecuted(uint256 proposalId) internal { - assertEq( - _timelock.getProposalDetails(proposalId).status, - ProposalStatus.Executed, - "TimelockProposal not in 'Executed' state" - ); - } - - function _assertProposalCancelled(uint256 proposalId) internal { - assertEq( - _timelock.getProposalDetails(proposalId).status, - ProposalStatus.Cancelled, - "Proposal not in 'Canceled' state" - ); - } - - function _assertNormalState() internal { - assertEq(_dualGovernance.getPersistedState(), DGState.Normal); - } - - function _assertVetoSignalingState() internal { - assertEq(_dualGovernance.getPersistedState(), DGState.VetoSignalling); - } - - function _assertVetoSignalingDeactivationState() internal { - assertEq(_dualGovernance.getPersistedState(), DGState.VetoSignallingDeactivation); - } - - function _assertRageQuitState() internal { - assertEq(_dualGovernance.getPersistedState(), DGState.RageQuit); - } - - function _assertVetoCooldownState() internal { - assertEq(_dualGovernance.getPersistedState(), DGState.VetoCooldown); - } - - function _assertNoTargetMockCalls() internal { - assertEq(_targetMock.getCalls().length, 0, "Unexpected target calls count"); - } - - // --- - // Logging and Debugging - // --- - function _logVetoSignallingState() internal view { - /* solhint-disable no-console */ - (bool isActive, uint256 duration, uint256 activatedAt, uint256 enteredAt) = _getVetoSignallingState(); - - if (!isActive) { - console.log("VetoSignalling state is not active\n"); - return; - } - - console.log("Veto signalling duration is %d seconds (%s)", duration, _formatDuration(_toDuration(duration))); - console.log("Veto signalling entered at %d (activated at %d)", enteredAt, activatedAt); - if (block.timestamp > activatedAt + duration) { - console.log( - "Veto signalling has ended %s ago\n", - _formatDuration(_toDuration(block.timestamp - activatedAt - duration)) - ); - } else { - console.log( - "Veto signalling will end after %s\n", - _formatDuration(_toDuration(activatedAt + duration - block.timestamp)) - ); - } - /* solhint-enable no-console */ - } - - function _logVetoSignallingDeactivationState() internal view { - /* solhint-disable no-console */ - (bool isActive, uint256 duration, uint256 enteredAt) = _getVetoSignallingDeactivationState(); - - if (!isActive) { - console.log("VetoSignallingDeactivation state is not active\n"); - return; - } - - console.log( - "VetoSignallingDeactivation duration is %d seconds (%s)", duration, _formatDuration(_toDuration(duration)) - ); - console.log("VetoSignallingDeactivation entered at %d", enteredAt); - if (block.timestamp > enteredAt + duration) { - console.log( - "VetoSignallingDeactivation has ended %s ago\n", - _formatDuration(_toDuration(block.timestamp - enteredAt - duration)) - ); - } else { - console.log( - "VetoSignallingDeactivation will end after %s\n", - _formatDuration(_toDuration(enteredAt + duration - block.timestamp)) - ); - } - /* solhint-enable no-console */ - } - - // --- - // Utils Methods - // --- - - function _step(string memory text) internal view { - // solhint-disable-next-line - console.log(string.concat(">>> ", text, " <<<")); - } - - function _wait(Duration duration) internal { - vm.warp(duration.addTo(Timestamps.now()).toSeconds()); - } - - function _waitAfterSubmitDelayPassed() internal { - _wait(_timelock.getAfterSubmitDelay() + Durations.from(1 seconds)); - } - - function _waitAfterScheduleDelayPassed() internal { - _wait(_timelock.getAfterScheduleDelay() + Durations.from(1 seconds)); - } - - function _executeActivateEmergencyMode() internal { - vm.prank(_emergencyActivationCommittee); - _timelock.activateEmergencyMode(); - } - - function _executeEmergencyExecute(uint256 proposalId) internal { - vm.prank(_emergencyExecutionCommittee); - _timelock.emergencyExecute(proposalId); - } - - function _executeEmergencyReset() internal { - vm.prank(_emergencyExecutionCommittee); - _timelock.emergencyReset(); - } - - struct DurationStruct { - uint256 _days; - uint256 _hours; - uint256 _minutes; - uint256 _seconds; - } - - function _toDuration(uint256 timestamp) internal pure returns (DurationStruct memory duration) { - duration._days = timestamp / 1 days; - duration._hours = (timestamp - 1 days * duration._days) / 1 hours; - duration._minutes = (timestamp - 1 days * duration._days - 1 hours * duration._hours) / 1 minutes; - duration._seconds = timestamp % 1 minutes; - } - - function _formatDuration(DurationStruct memory duration) internal pure returns (string memory) { - // format example: 1d:22h:33m:12s - return string( - abi.encodePacked( - Strings.toString(duration._days), - "d:", - Strings.toString(duration._hours), - "h:", - Strings.toString(duration._minutes), - "m:", - Strings.toString(duration._seconds), - "s" - ) - ); - } -} diff --git a/test/utils/testing-assert-eq-extender.sol b/test/utils/testing-assert-eq-extender.sol index fc9d6571..d39e1db4 100644 --- a/test/utils/testing-assert-eq-extender.sol +++ b/test/utils/testing-assert-eq-extender.sol @@ -33,6 +33,10 @@ contract TestingAssertEqExtender is Test { assertEq(uint256(Timestamp.unwrap(a)), uint256(Timestamp.unwrap(b))); } + function assertEq(Timestamp a, Timestamp b, string memory message) internal { + assertEq(uint256(Timestamp.unwrap(a)), uint256(Timestamp.unwrap(b)), message); + } + function assertEq(ProposalStatus a, ProposalStatus b) internal { assertEq(uint256(a), uint256(b)); } diff --git a/test/utils/time-constraints.sol b/test/utils/time-constraints.sol index c8cd6203..15f1a082 100644 --- a/test/utils/time-constraints.sol +++ b/test/utils/time-constraints.sol @@ -1,3 +1,4 @@ +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: MIT pragma solidity 0.8.26; @@ -15,6 +16,7 @@ contract TimeConstraints { error InvalidDayTimeRange(Duration startDayTime, Duration endDayTime); error DayTimeOutOfRange(Duration currentDayTime, Duration startDayTime, Duration endDayTime); error TimestampNotReached(Timestamp requiredTimestamp); + error TimestampExceeded(Timestamp deadline); // --- // Constants @@ -52,6 +54,14 @@ contract TimeConstraints { } } + /// @notice Checks that the transaction can only be executed before a specific timestamp. + /// @param timestamp The Unix timestamp before which the function can be executed. + function checkExecuteBeforeTimestamp(Timestamp timestamp) external view { + if (Timestamps.now() > timestamp) { + revert TimestampExceeded(timestamp); + } + } + // --- // Getters // --- diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 4ce5fa17..00000000 --- a/yarn.lock +++ /dev/null @@ -1,4185 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@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": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@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": - 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": - 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": - 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": - 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": - 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== - -"@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": - 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.4.2", "@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== - dependencies: - "@noble/hashes" "1.4.0" - -"@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.4.0", "@noble/hashes@^1.4.0", "@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": - 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.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.1.tgz#210e6b5eaff9278814e8f19800182d1071554855" - integrity sha512-XuiUUnWAVNw7JYv7nRqDWfpBm21HOxCRBQ8lQnRnmiets9Ss2X5Ul9mvBheIPh/D0wBzwJ8TRtsSrorpwE79cA== - -"@nomicfoundation/edr-darwin-x64@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.1.tgz#81e660de77d1d73317c9a5140349d1197cddef9a" - integrity sha512-N1MfJqEX5ixaXlyyrHnaYxzwIT27Nc/jUgLI7ts4/9kRvPTvyZRYmXS1ciKhmUFr/WvFckTCix2RJbZoGGtX7g== - -"@nomicfoundation/edr-linux-arm64-gnu@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.1.tgz#6e1ce12080a35505c7f3eaf772f4e171db8b7f9a" - integrity sha512-bSPOfmcFjJwDgWOV5kgZHeqg2OWu1cINrHSGjig0aVHehjcoX4Sgayrj6fyAxcOV5NQKA6WcyTFll6NrCxzWRA== - -"@nomicfoundation/edr-linux-arm64-musl@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.1.tgz#a467a6c8631053d10a8641f67618b9bdf057c636" - integrity sha512-F/+DgOdeBFQDrk+SX4aFffJFBgJfd75ZtE2mjcWNAh/qWiS7NfUxdQX/5OvNo/H6EY4a+3bZH6Bgzqg4mEWvMw== - -"@nomicfoundation/edr-linux-x64-gnu@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.1.tgz#63753d05767b4bc0d4f9f9be8399928c790c931e" - integrity sha512-POHhTWczIXCPhzKtY0Vt/l+VCqqCx5gNR5ErwSrNnLz/arfQobZFAU+nc61BX3Jch82TW8b3AbfGI73Kh7gO0w== - -"@nomicfoundation/edr-linux-x64-musl@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.1.tgz#44d128b9a09e3f61b08617213a58cd84dd15c418" - integrity sha512-uu8oNp4Ozg3H1x1We0FF+rwXfFiAvsOm5GQ+OBx9YYOXnfDPWqguQfGIkhrti9GD0iYhfQ/WOG5wvp0IzzgGSg== - -"@nomicfoundation/edr-win32-x64-msvc@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.1.tgz#1667b725337ca6f27ec58c63337b6a62a0d7ed09" - integrity sha512-PaZHFw455z89ZiKYNTnKu+/TiVZVRI+mRJsbRTe2N0VlYfUBS1o2gdXBM12oP1t198HR7xQwEPPAslTFxGBqHA== - -"@nomicfoundation/edr@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.1.tgz#7d698454d228ffc5399f1c58799104b53e1b60ae" - integrity sha512-NgrMo2rI9r28uidumvd+K2/AJLdxtXsUlJr3hj/pM6S1FCd/HiWaLeLa/cjCVPcE2u1rYAa3W6UFxLCB7S5Dhw== - dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.4.1" - "@nomicfoundation/edr-darwin-x64" "0.4.1" - "@nomicfoundation/edr-linux-arm64-gnu" "0.4.1" - "@nomicfoundation/edr-linux-arm64-musl" "0.4.1" - "@nomicfoundation/edr-linux-x64-gnu" "0.4.1" - "@nomicfoundation/edr-linux-x64-musl" "0.4.1" - "@nomicfoundation/edr-win32-x64-msvc" "0.4.1" - -"@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.0": - 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-foundry@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-foundry/-/hardhat-foundry-1.1.2.tgz#4f5aaa1803b8f5d974dcbc361beb72d49c815562" - integrity sha512-f5Vhj3m2qvKGpr6NAINYwNgILDsai8dVCsFb1rAVLkJxOmD2pAtfCmOH5SBVr9yUI5B1z9rbTwPBJVrqnb+PXQ== - dependencies: - chalk "^2.4.2" - -"@nomicfoundation/hardhat-network-helpers@^1.0.0": - 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@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-3.0.0.tgz#83e2c28a745aa4eb1236072166367b0de68b4c76" - integrity sha512-MsteDXd0UagMksqm9KvcFG6gNKYNa3GGNCy73iQ6bEasEgg2v8Qjl6XA5hjs8o5UD5A3153B6W2BIVJ8SxYUtA== - -"@nomicfoundation/hardhat-verify@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-1.1.1.tgz#6a433d777ce0172d1f0edf7f2d3e1df14b3ecfc1" - integrity sha512-9QsTYD7pcZaQFEA3tBb/D/oCStYDiEVDN7Dxeo/4SCyHRSm86APypxxdOMEPlGmXsAvd+p1j/dTODcpxb8aztA== - 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.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" - integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" - integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" - integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" - integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" - integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" - integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" - integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" - integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" - -"@openzeppelin/contracts@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.1.tgz#93da90fc209a0a4ff09c1deb037fbb35e4020890" - integrity sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w== - -"@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" - -"@scure/base@~1.1.0", "@scure/base@~1.1.6": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" - integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== - -"@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.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== - dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@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.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" - integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== - dependencies: - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@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.14.0": - version "0.14.5" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" - integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@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" - -"@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@*": - version "4.3.16" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" - integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== - -"@types/concat-stream@^1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" - integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== - dependencies: - "@types/node" "*" - -"@types/form-data@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" - integrity sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw== - dependencies: - "@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/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/node@*": - version "20.14.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" - integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== - 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/node@^10.0.3": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - -"@types/node@^8.0.0": - version "8.10.66" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" - integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== - -"@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/qs@^6.2.31": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== - -"@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" "*" - -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== - -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.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.16.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" - integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== - 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, ansi-colors@^4.1.3: - 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-escapes@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" - integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -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.0.0, ansi-styles@^6.2.1: - 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== - -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== - -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" - -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-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== - -array-uniq@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== - -asap@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -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== - -axios@^1.5.1: - 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.10" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" - integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== - 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== - -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== - -caseless@^0.12.0, caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - -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.2.0: - 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@^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" - -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@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== - -"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.4.0, chokidar@^3.5.3: - 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-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== - dependencies: - restore-cursor "^4.0.0" - -cli-table3@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== - dependencies: - object-assign "^4.1.0" - string-width "^2.1.1" - optionalDependencies: - colors "^1.1.2" - -cli-truncate@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a" - integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== - dependencies: - slice-ansi "^5.0.0" - string-width "^7.0.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== - -colorette@^2.0.20: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -colors@1.4.0, colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -combined-stream@^1.0.6, 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== - -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== - -commander@^8.1.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -commander@~12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - -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== - -concat-stream@^1.6.0, concat-stream@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -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== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -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" - -cross-spawn@^7.0.3: - 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.1, debug@^4.3.5, 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" - -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.4" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" - integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== - dependencies: - type-detect "^4.0.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: - 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.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" - integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== - -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" - -dotenv@^16.3.1: - version "16.4.5" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" - integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== - -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@^10.3.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" - integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw== - -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== - -enquirer@^2.3.0: - 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@^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== - -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== - -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" - -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== - -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== - -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== - -eth-gas-reporter@^0.2.25: - version "0.2.27" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz#928de8548a674ed64c7ba0bf5795e63079150d4e" - integrity sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw== - dependencies: - "@solidity-parser/parser" "^0.14.0" - axios "^1.5.1" - cli-table3 "^0.5.0" - colors "1.4.0" - ethereum-cryptography "^1.0.3" - ethers "^5.7.2" - fs-readdir-recursive "^1.1.0" - lodash "^4.17.14" - markdown-table "^1.1.3" - mocha "^10.2.0" - req-cwd "^2.0.0" - sha1 "^1.1.1" - sync-request "^6.0.0" - -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: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" - integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== - dependencies: - "@noble/curves" "1.4.2" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" - "@scure/bip39" "1.3.0" - -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.2: - 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.4.0: - version "6.13.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.1.tgz#2b9f9c7455cde9d38b30fe6589972eb083652961" - integrity sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A== - 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.17.1" - -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" - -eventemitter3@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" - integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== - -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" - -execa@~8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" - integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^8.0.1" - human-signals "^5.0.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^4.1.0" - strip-final-newline "^3.0.0" - -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.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: - 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: - 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" - -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-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" - -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" - -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== - -follow-redirects@^1.12.1, 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== - -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@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -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@^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-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - -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-east-asian-width@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e" - integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA== - -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-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg== - -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== - -get-stream@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" - integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== - -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@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@^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.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" - -glob@^8.0.3, glob@^8.1.0: - 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" - -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" - -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" - -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.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== - -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-gas-reporter@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz#ebe5bda5334b5def312747580cd923c2b09aef1b" - integrity sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA== - dependencies: - array-uniq "1.0.3" - eth-gas-reporter "^0.2.25" - sha1 "^1.1.1" - -hardhat@^2.17.2: - version "2.22.6" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.6.tgz#d73caece246cd8219a1815554dabc31d400fa035" - integrity sha512-abFEnd9QACwEtSvZZGSmzvw7N3zhQN1cDKz5SLHAupfG24qTHofCjqvD5kT5Wwsq5XOL0ON1Mq5rr4v0XX5ciw== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/edr" "^0.4.1" - "@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.8.26" - 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, hasown@^2.0.2: - 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-basic@^8.1.1: - version "8.1.3" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" - integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== - dependencies: - caseless "^0.12.0" - concat-stream "^1.6.2" - http-response-object "^3.0.1" - parse-cache-control "^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" - -http-response-object@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" - integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== - dependencies: - "@types/node" "^10.0.3" - -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" - -human-signals@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" - integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== - -husky@^9.0.10: - version "9.0.11" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" - integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== - -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.4: - 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.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" - -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, inherits@~2.0.3: - 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.14.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" - integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== - dependencies: - hasown "^2.0.2" - -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@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -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-fullwidth-code-point@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" - integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== - -is-fullwidth-code-point@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704" - integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA== - dependencies: - get-east-asian-width "^1.0.0" - -is-glob@^4.0.1, 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-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-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - -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== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -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: - 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" - -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== - -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" - -jsonschema@^1.2.4: - 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: - 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== - -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.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" - -lilconfig@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" - integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== - -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== - -lint-staged@^15.2.2: - version "15.2.7" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.7.tgz#97867e29ed632820c0fb90be06cd9ed384025649" - integrity sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw== - dependencies: - chalk "~5.3.0" - commander "~12.1.0" - debug "~4.3.4" - execa "~8.0.1" - lilconfig "~3.1.1" - listr2 "~8.2.1" - micromatch "~4.0.7" - pidtree "~0.6.0" - string-argv "~0.3.2" - yaml "~2.4.2" - -listr2@~8.2.1: - version "8.2.3" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.3.tgz#c494bb89b34329cf900e4e0ae8aeef9081d7d7a5" - integrity sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw== - dependencies: - cli-truncate "^4.0.0" - colorette "^2.0.20" - eventemitter3 "^5.0.1" - log-update "^6.0.0" - rfdc "^1.4.1" - wrap-ansi "^9.0.0" - -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.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.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.14, 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" - -log-update@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59" - integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw== - dependencies: - ansi-escapes "^6.2.0" - cli-cursor "^4.0.0" - slice-ansi "^7.0.0" - strip-ansi "^7.1.0" - wrap-ansi "^9.0.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_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== - -markdown-table@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" - integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== - -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== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.2.3, merge2@^1.3.0: - 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, micromatch@~4.0.7: - 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-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -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: - 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, minimatch@^5.1.6: - 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" - -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== - -mkdirp@0.5.x: - 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" - -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.6.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.6.0.tgz#465fc66c52613088e10018989a3b98d5e11954b9" - integrity sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw== - dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.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.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^16.2.0" - yargs-parser "^20.2.9" - 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== - -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== - -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - -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-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== - -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" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - -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" - -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-cache-control@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" - integrity sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg== - -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-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - -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-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== - -pidtree@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" - integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== - -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.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@^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== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise@^8.0.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" - integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== - dependencies: - asap "~2.0.6" - -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.4.0: - version "6.12.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754" - integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ== - 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@^2.2.2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.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" - -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" - -req-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" - integrity sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ== - dependencies: - req-from "^2.0.0" - -req-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" - integrity sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA== - dependencies: - resolve-from "^3.0.0" - -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.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@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - -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: - 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" - -restore-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -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== - -rfdc@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" - integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== - -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== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"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: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - 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@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -signal-exit@^4.1.0: - 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" - -slice-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" - integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== - dependencies: - ansi-styles "^6.0.0" - is-fullwidth-code-point "^4.0.0" - -slice-ansi@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9" - integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== - dependencies: - ansi-styles "^6.2.1" - is-fullwidth-code-point "^5.0.0" - -solc@0.8.26: - version "0.8.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" - integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== - dependencies: - command-exists "^1.2.8" - commander "^8.1.0" - follow-redirects "^1.12.1" - js-sha3 "0.8.0" - memorystream "^0.3.1" - semver "^5.5.0" - tmp "0.0.33" - -solhint-plugin-lido@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/solhint-plugin-lido/-/solhint-plugin-lido-0.0.4.tgz#a1f64970b7d58a94c1dfa98bae1ff83615cc0548" - integrity sha512-c+MsZY8zfVahIekswH04baEymE4foUS4oq62nKodUOEJ9mbkMACDszx7zevlAePW/77EBd2NONZdnRPy9WvpFQ== - -solhint@^4.1.1: - version "4.5.4" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-4.5.4.tgz#171cf33f46c36b8499efe60c0e425f6883a54e50" - integrity sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ== - 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-coverage@^0.8.4: - 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.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-argv@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" - integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== - -string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.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== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" - integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== - dependencies: - emoji-regex "^10.3.0" - get-east-asian-width "^1.0.0" - strip-ansi "^7.1.0" - -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" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -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.1.0: - 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-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - -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: - 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@^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-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-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== - -sync-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" - integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== - dependencies: - http-response-object "^3.0.1" - sync-rpc "^1.2.1" - then-request "^6.0.0" - -sync-rpc@^1.2.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" - integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== - dependencies: - get-port "^3.1.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== - -then-request@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" - integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/form-data" "0.0.33" - "@types/node" "^8.0.0" - "@types/qs" "^6.2.31" - caseless "~0.12.0" - concat-stream "^1.6.0" - form-data "^2.2.0" - http-basic "^8.1.1" - http-response-object "^3.0.1" - promise "^8.0.0" - qs "^6.4.0" - -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-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== - -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.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== - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - -uglify-js@^3.1.4: - version "3.18.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.18.0.tgz#73b576a7e8fda63d2831e293aeead73e0a270deb" - integrity sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A== - -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== - -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, 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== - -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.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== - -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== - -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@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" - integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== - dependencies: - ansi-styles "^6.2.1" - string-width "^7.0.0" - strip-ansi "^7.1.0" - -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.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== - -ws@^7.4.6: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - -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== - -yaml@~2.4.2: - version "2.4.5" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" - integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== - -yargs-parser@^20.2.2, yargs-parser@^20.2.9: - 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" - -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==