From 514d91691de10c9da0a8a538228f94a5d5e8e37e Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Mon, 12 Feb 2024 15:47:14 +0200 Subject: [PATCH 01/29] Add blocklist factory, update exit queue --- .github/workflows/CI.yaml | 3 + .gitignore | 2 +- abi/Errors.json | 14 +- abi/IEthBlocklistErc20Vault.json | 1595 +++++++++++++ abi/IEthBlocklistVault.json | 1298 +++++++++++ abi/IEthErc20Vault.json | 107 +- abi/IEthFoxVault.json | 107 +- abi/IEthGenesisVault.json | 107 +- abi/IEthPrivErc20Vault.json | 120 +- abi/IEthPrivVault.json | 120 +- abi/IEthVault.json | 107 +- abi/IRewardSplitter.json | 24 - abi/IVaultEnterExit.json | 107 +- abi/IVaultEthStaking.json | 107 +- abi/IVaultMev.json | 26 +- abi/IVaultOsToken.json | 107 +- abi/IVaultState.json | 26 +- abi/IVaultToken.json | 107 +- abi/IVaultValidators.json | 26 +- .../interfaces/IEthBlocklistErc20Vault.sol | 20 + contracts/interfaces/IEthBlocklistVault.sol | 20 + contracts/interfaces/IEthErc20Vault.sol | 2 +- contracts/interfaces/IEthFoxVault.sol | 2 +- contracts/interfaces/IEthPrivErc20Vault.sol | 9 +- contracts/interfaces/IEthPrivVault.sol | 9 +- contracts/interfaces/IEthVault.sol | 2 +- contracts/interfaces/IRewardSplitter.sol | 8 - contracts/interfaces/IVaultEnterExit.sol | 46 +- contracts/interfaces/IVaultState.sol | 8 +- contracts/libraries/Errors.sol | 4 +- contracts/libraries/ExitQueue.sol | 15 + contracts/misc/RewardSplitter.sol | 6 - ...VaultV2Mock.sol => EthPrivVaultV3Mock.sol} | 6 +- contracts/mocks/EthVaultV3Mock.sol | 16 +- ...{EthVaultV2Mock.sol => EthVaultV4Mock.sol} | 18 +- .../ethereum/EthBlocklistErc20Vault.sol | 152 ++ .../vaults/ethereum/EthBlocklistVault.sol | 139 ++ contracts/vaults/ethereum/EthErc20Vault.sol | 54 +- contracts/vaults/ethereum/EthGenesisVault.sol | 24 +- .../vaults/ethereum/EthPrivErc20Vault.sol | 96 +- contracts/vaults/ethereum/EthPrivVault.sol | 70 +- contracts/vaults/ethereum/EthVault.sol | 40 +- .../vaults/ethereum/custom/EthFoxVault.sol | 32 +- contracts/vaults/modules/VaultAdmin.sol | 1 + contracts/vaults/modules/VaultEnterExit.sol | 189 +- contracts/vaults/modules/VaultImmutables.sol | 17 +- contracts/vaults/modules/VaultOsToken.sol | 57 +- contracts/vaults/modules/VaultState.sol | 81 +- contracts/vaults/modules/VaultToken.sol | 6 - contracts/vaults/modules/VaultWhitelist.sol | 18 +- helpers/constants.ts | 57 +- test/EthBlocklistErc20Vault.spec.ts | 320 +++ test/EthBlocklistVault.spec.ts | 281 +++ test/EthErc20Vault.spec.ts | 104 +- test/EthFoxVault.spec.ts | 17 +- test/EthGenesisVault.spec.ts | 60 +- test/EthPrivErc20Vault.spec.ts | 164 +- test/EthPrivVault.spec.ts | 202 ++ test/EthVault.deposit.spec.ts | 1 - test/EthVault.multicall.spec.ts | 2 +- test/EthVault.register.spec.ts | 2 +- test/EthVault.state.spec.ts | 93 +- test/EthVault.upgrade.spec.ts | 246 +- test/EthVault.whitelist.spec.ts | 8 +- test/EthVault.withdraw.spec.ts | 1230 +++++----- test/EthVaultFactory.spec.ts | 2 +- .../EthBlocklistErc20Vault.spec.ts.snap | 57 + .../EthBlocklistVault.spec.ts.snap | 50 + test/__snapshots__/EthErc20Vault.spec.ts.snap | 13 +- test/__snapshots__/EthFoxVault.spec.ts.snap | 21 +- .../EthGenesisVault.spec.ts.snap | 10 +- .../EthPrivErc20Vault.spec.ts.snap | 39 +- test/__snapshots__/EthPrivVault.spec.ts.snap | 36 + test/__snapshots__/EthVault.burn.spec.ts.snap | 4 +- .../EthVault.deposit.spec.ts.snap | 6 +- .../EthVault.liquidate.spec.ts.snap | 4 +- test/__snapshots__/EthVault.mint.spec.ts.snap | 4 +- .../EthVault.multicall.spec.ts.snap | 4 +- .../EthVault.redeem.spec.ts.snap | 4 +- .../EthVault.register.spec.ts.snap | 4 +- .../EthVault.settings.spec.ts.snap | 6 +- .../__snapshots__/EthVault.state.spec.ts.snap | 9 +- .../__snapshots__/EthVault.token.spec.ts.snap | 10 +- .../EthVault.upgrade.spec.ts.snap | 44 +- .../EthVault.whitelist.spec.ts.snap | 8 +- .../EthVault.withdraw.spec.ts.snap | 21 +- .../EthVaultFactory.spec.ts.snap | 16 +- .../KeeperValidators.spec.ts.snap | 8 +- .../__snapshots__/RewardSplitter.spec.ts.snap | 10 +- .../__snapshots__/VaultsRegistry.spec.ts.snap | 2 +- test/shared/artifacts/EthErc20Vault.json | 1908 ++++++++++++++++ test/shared/artifacts/EthGenesisVault.json | 1709 ++++++++++++++ test/shared/artifacts/EthPrivErc20Vault.json | 2020 +++++++++++++++++ test/shared/artifacts/EthPrivVault.json | 1708 ++++++++++++++ .../artifacts/EthValidatorsRegistry.json | 120 + test/shared/artifacts/EthVault.json | 1596 +++++++++++++ test/shared/constants.ts | 2 +- test/shared/contracts.ts | 29 +- test/shared/fixtures.ts | 135 +- test/shared/rewards.ts | 38 +- test/shared/types.ts | 17 + test/shared/validators.ts | 11 +- 102 files changed, 15548 insertions(+), 2201 deletions(-) create mode 100644 abi/IEthBlocklistErc20Vault.json create mode 100644 abi/IEthBlocklistVault.json create mode 100644 contracts/interfaces/IEthBlocklistErc20Vault.sol create mode 100644 contracts/interfaces/IEthBlocklistVault.sol rename contracts/mocks/{EthPrivVaultV2Mock.sol => EthPrivVaultV3Mock.sol} (90%) rename contracts/mocks/{EthVaultV2Mock.sol => EthVaultV4Mock.sol} (61%) create mode 100644 contracts/vaults/ethereum/EthBlocklistErc20Vault.sol create mode 100644 contracts/vaults/ethereum/EthBlocklistVault.sol create mode 100644 test/EthBlocklistErc20Vault.spec.ts create mode 100644 test/EthBlocklistVault.spec.ts create mode 100644 test/EthPrivVault.spec.ts create mode 100644 test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap create mode 100644 test/__snapshots__/EthBlocklistVault.spec.ts.snap create mode 100644 test/__snapshots__/EthPrivVault.spec.ts.snap create mode 100644 test/shared/artifacts/EthErc20Vault.json create mode 100644 test/shared/artifacts/EthGenesisVault.json create mode 100644 test/shared/artifacts/EthPrivErc20Vault.json create mode 100644 test/shared/artifacts/EthPrivVault.json create mode 100644 test/shared/artifacts/EthValidatorsRegistry.json create mode 100644 test/shared/artifacts/EthVault.json diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 04de2c3d..93de507d 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -51,6 +51,9 @@ jobs: - run: npm run compile env: { SKIP_LOAD: true } - run: npm run test:gas + env: + SKIP_LOAD: true + - run: npm run test:fork env: SKIP_LOAD: true MAINNET_FORK_RPC_URL: ${{ secrets.MAINNET_FORK_RPC_URL }} diff --git a/.gitignore b/.gitignore index ac5b4cc5..06143372 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ npm-debug.log # Hardhat cache -artifacts +/artifacts # Typechain /typechain-types diff --git a/abi/Errors.json b/abi/Errors.json index 15344060..56dcc0c3 100644 --- a/abi/Errors.json +++ b/abi/Errors.json @@ -21,17 +21,12 @@ }, { "inputs": [], - "name": "ClaimTooEarly", - "type": "error" - }, - { - "inputs": [], - "name": "Collateralized", + "name": "DeadlineExpired", "type": "error" }, { "inputs": [], - "name": "DeadlineExpired", + "name": "ExitRequestNotProcessed", "type": "error" }, { @@ -219,11 +214,6 @@ "name": "UpgradeFailed", "type": "error" }, - { - "inputs": [], - "name": "WhitelistAlreadyUpdated", - "type": "error" - }, { "inputs": [], "name": "ZeroAddress", diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json new file mode 100644 index 00000000..986ea4c5 --- /dev/null +++ b/abi/IEthBlocklistErc20Vault.json @@ -0,0 +1,1595 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "blocklistManager", + "type": "address" + } + ], + "name": "BlocklistManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isBlocked", + "type": "bool" + } + ], + "name": "BlocklistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "blockedAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocklistManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ejectUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_blocklistManager", + "type": "address" + } + ], + "name": "setBlocklistManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keysManager", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBlocked", + "type": "bool" + } + ], + "name": "updateBlocklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json new file mode 100644 index 00000000..77ccfcde --- /dev/null +++ b/abi/IEthBlocklistVault.json @@ -0,0 +1,1298 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "blocklistManager", + "type": "address" + } + ], + "name": "BlocklistManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isBlocked", + "type": "bool" + } + ], + "name": "BlocklistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "blockedAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blocklistManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ejectUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_blocklistManager", + "type": "address" + } + ], + "name": "setBlocklistManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_keysManager", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBlocked", + "type": "bool" + } + ], + "name": "updateBlocklist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index 42edc849..a6c94340 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -120,12 +120,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -372,37 +366,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -648,23 +611,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -1074,19 +1021,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -1094,30 +1028,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1319,6 +1229,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index 1a7aed4f..b7c90a72 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -160,7 +160,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -176,12 +176,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -280,37 +274,6 @@ "name": "MetadataUpdated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -483,23 +446,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -763,19 +710,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -783,30 +717,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -985,6 +895,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index 1138e1bd..ffef15db 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -403,37 +397,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -581,23 +544,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -943,19 +890,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -963,30 +897,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1175,6 +1085,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 0204abed..26f443ca 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -120,12 +120,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -372,37 +366,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -692,23 +655,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -787,6 +734,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ejectUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1118,19 +1078,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -1138,30 +1085,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1376,6 +1299,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index 9a230124..765b48b9 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -347,37 +341,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -562,23 +525,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -644,6 +591,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "ejectUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -900,19 +860,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -920,30 +867,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1145,6 +1068,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IEthVault.json b/abi/IEthVault.json index f32b55ed..b99791c4 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -347,37 +341,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -518,23 +481,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -856,19 +803,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -876,30 +810,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1088,6 +998,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IRewardSplitter.json b/abi/IRewardSplitter.json index 9d994392..093a4cba 100644 --- a/abi/IRewardSplitter.json +++ b/abi/IRewardSplitter.json @@ -218,30 +218,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "rewards", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/abi/IVaultEnterExit.json b/abi/IVaultEnterExit.json index 6c0e285a..4648c227 100644 --- a/abi/IVaultEnterExit.json +++ b/abi/IVaultEnterExit.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -180,37 +174,6 @@ "name": "MetadataUpdated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "inputs": [], "name": "admin", @@ -300,23 +263,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -459,43 +406,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -535,6 +445,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index ad3ff60b..95af2719 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -199,37 +193,6 @@ "name": "MetadataUpdated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -351,23 +314,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -560,19 +507,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "receiveFromMevEscrow", @@ -580,30 +514,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -769,6 +679,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultMev.json b/abi/IVaultMev.json index 7f267dbe..59aaee4c 100644 --- a/abi/IVaultMev.json +++ b/abi/IVaultMev.json @@ -216,19 +216,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -268,6 +255,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultOsToken.json b/abi/IVaultOsToken.json index 81f5fb69..0dcfe754 100644 --- a/abi/IVaultOsToken.json +++ b/abi/IVaultOsToken.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -95,12 +95,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -328,37 +322,6 @@ "name": "OsTokenRedeemed", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "inputs": [], "name": "admin", @@ -467,23 +430,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -697,43 +644,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -796,6 +706,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultState.json b/abi/IVaultState.json index 1c69075a..1dd827b8 100644 --- a/abi/IVaultState.json +++ b/abi/IVaultState.json @@ -203,19 +203,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -255,6 +242,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultToken.json b/abi/IVaultToken.json index 6e4f52d7..4a437759 100644 --- a/abi/IVaultToken.json +++ b/abi/IVaultToken.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "shares", + "name": "assets", "type": "uint256" } ], @@ -120,12 +120,6 @@ "name": "receiver", "type": "address" }, - { - "indexed": false, - "internalType": "uint256", - "name": "prevPositionTicket", - "type": "uint256" - }, { "indexed": false, "internalType": "uint256", @@ -205,37 +199,6 @@ "name": "MetadataUpdated", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "assets", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "shares", - "type": "uint256" - } - ], - "name": "Redeemed", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -430,23 +393,7 @@ } ], "name": "claimExitedAssets", - "outputs": [ - { - "internalType": "uint256", - "name": "newPositionTicket", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedShares", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "claimedAssets", - "type": "uint256" - } - ], + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -677,43 +624,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "shares", - "type": "uint256" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "redeem", - "outputs": [ - { - "internalType": "uint256", - "name": "assets", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -766,6 +676,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/abi/IVaultValidators.json b/abi/IVaultValidators.json index ea8e91a3..60229b1b 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -267,19 +267,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "queuedShares", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -445,6 +432,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalExitingAssets", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalShares", diff --git a/contracts/interfaces/IEthBlocklistErc20Vault.sol b/contracts/interfaces/IEthBlocklistErc20Vault.sol new file mode 100644 index 00000000..489d6b55 --- /dev/null +++ b/contracts/interfaces/IEthBlocklistErc20Vault.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultBlocklist} from './IVaultBlocklist.sol'; +import {IEthErc20Vault} from './IEthErc20Vault.sol'; + +/** + * @title IEthBlocklistErc20Vault + * @author StakeWise + * @notice Defines the interface for the EthBlocklistErc20Vault contract + */ +interface IEthBlocklistErc20Vault is IEthErc20Vault, IVaultBlocklist { + /** + * @notice Function for ejecting user from the vault. Can be called only by the blocklist manager. + * The user will be added to the blocklist and placed to the exit queue. + * @param user The address of the user + */ + function ejectUser(address user) external; +} diff --git a/contracts/interfaces/IEthBlocklistVault.sol b/contracts/interfaces/IEthBlocklistVault.sol new file mode 100644 index 00000000..e7df7331 --- /dev/null +++ b/contracts/interfaces/IEthBlocklistVault.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultBlocklist} from './IVaultBlocklist.sol'; +import {IEthVault} from './IEthVault.sol'; + +/** + * @title IEthBlocklistVault + * @author StakeWise + * @notice Defines the interface for the EthBlocklistVault contract + */ +interface IEthBlocklistVault is IEthVault, IVaultBlocklist { + /** + * @notice Function for ejecting user from the vault. Can be called only by the blocklist manager. + * The user will be added to the blocklist and placed to the exit queue. + * @param user The address of the user + */ + function ejectUser(address user) external; +} diff --git a/contracts/interfaces/IEthErc20Vault.sol b/contracts/interfaces/IEthErc20Vault.sol index 7392c310..8ea2a0df 100644 --- a/contracts/interfaces/IEthErc20Vault.sol +++ b/contracts/interfaces/IEthErc20Vault.sol @@ -49,7 +49,7 @@ interface IEthErc20Vault is } /** - * @notice Initializes the EthErc20Vault contract. Must transfer security deposit together with a call. + * @notice Initializes or upgrades the EthErc20Vault contract. Must transfer security deposit during the deployment. * @param params The encoded parameters for initializing the EthErc20Vault contract */ function initialize(bytes calldata params) external payable; diff --git a/contracts/interfaces/IEthFoxVault.sol b/contracts/interfaces/IEthFoxVault.sol index b024869b..f73b8d39 100644 --- a/contracts/interfaces/IEthFoxVault.sol +++ b/contracts/interfaces/IEthFoxVault.sol @@ -71,7 +71,7 @@ interface IEthFoxVault is ); /** - * @notice Initializes the EthFoxVault contract. Must transfer security deposit together with a call. + * @notice Initializes or upgrades the EthFoxVault contract. Must transfer security deposit during the deployment. * @param params The encoded parameters for initializing the EthFoxVault contract */ function initialize(bytes calldata params) external payable; diff --git a/contracts/interfaces/IEthPrivErc20Vault.sol b/contracts/interfaces/IEthPrivErc20Vault.sol index 0fbab335..7f23e8b4 100644 --- a/contracts/interfaces/IEthPrivErc20Vault.sol +++ b/contracts/interfaces/IEthPrivErc20Vault.sol @@ -10,4 +10,11 @@ import {IEthErc20Vault} from './IEthErc20Vault.sol'; * @author StakeWise * @notice Defines the interface for the EthPrivErc20Vault contract */ -interface IEthPrivErc20Vault is IEthErc20Vault, IVaultWhitelist {} +interface IEthPrivErc20Vault is IEthErc20Vault, IVaultWhitelist { + /** + * @notice Function for ejecting user from the vault. Can only be called by the whitelister. + * The user will be removed from the whitelist and placed to the exit queue. + * @param user The address of the user + */ + function ejectUser(address user) external; +} diff --git a/contracts/interfaces/IEthPrivVault.sol b/contracts/interfaces/IEthPrivVault.sol index 75ef0117..067cd8ae 100644 --- a/contracts/interfaces/IEthPrivVault.sol +++ b/contracts/interfaces/IEthPrivVault.sol @@ -10,4 +10,11 @@ import {IEthVault} from './IEthVault.sol'; * @author StakeWise * @notice Defines the interface for the EthPrivVault contract */ -interface IEthPrivVault is IEthVault, IVaultWhitelist {} +interface IEthPrivVault is IEthVault, IVaultWhitelist { + /** + * @notice Function for ejecting user from the vault. Can only be called by the whitelister. + * The user will be removed from the whitelist and placed to the exit queue. + * @param user The address of the user + */ + function ejectUser(address user) external; +} diff --git a/contracts/interfaces/IEthVault.sol b/contracts/interfaces/IEthVault.sol index ca95e5ae..80239e5b 100644 --- a/contracts/interfaces/IEthVault.sol +++ b/contracts/interfaces/IEthVault.sol @@ -43,7 +43,7 @@ interface IEthVault is } /** - * @notice Initializes the EthVault contract. Must transfer security deposit together with a call. + * @notice Initializes or upgrades the EthVault contract. Must transfer security deposit during the deployment. * @param params The encoded parameters for initializing the EthVault contract */ function initialize(bytes calldata params) external payable; diff --git a/contracts/interfaces/IRewardSplitter.sol b/contracts/interfaces/IRewardSplitter.sol index 97b5d024..88479a36 100644 --- a/contracts/interfaces/IRewardSplitter.sol +++ b/contracts/interfaces/IRewardSplitter.sol @@ -132,14 +132,6 @@ interface IRewardSplitter is IMulticall { address receiver ) external returns (uint256 positionTicket); - /** - * @notice Redeems available assets from the vault - * @param rewards The amount of rewards to redeem - * @param receiver The address that will receive the redeemed assets - * @return assets The amount of assets that were redeemed - */ - function redeem(uint256 rewards, address receiver) external returns (uint256 assets); - /** * @notice Syncs the rewards from the vault to the splitter. The vault state must be up-to-date. */ diff --git a/contracts/interfaces/IVaultEnterExit.sol b/contracts/interfaces/IVaultEnterExit.sol index b72f3cf2..359dd7ac 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -26,46 +26,35 @@ interface IVaultEnterExit is IVaultState { address referrer ); - /** - * @notice Event emitted on redeem - * @param owner The address that owns the shares - * @param receiver The address that received withdrawn assets - * @param assets The total number of withdrawn assets - * @param shares The total number of withdrawn shares - */ - event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); - /** * @notice Event emitted on shares added to the exit queue * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position - * @param shares The number of shares that queued for the exit + * @param assets The number of assets that queued for the exit */ event ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, - uint256 shares + uint256 assets ); /** * @notice Event emitted on claim of the exited assets * @param receiver The address that has received withdrawn assets - * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call - * @param newPositionTicket The new exit queue ticket in case not all the shares were withdrawn. Otherwise 0. + * @param newPositionTicket The new exit queue ticket in case not all the assets were withdrawn. Otherwise 0. * @param withdrawnAssets The total number of assets withdrawn */ event ExitedAssetsClaimed( address indexed receiver, - uint256 prevPositionTicket, uint256 newPositionTicket, uint256 withdrawnAssets ); /** - * @notice Locks shares to the exit queue. The shares continue earning rewards until they will be burned by the Vault. - * @param shares The number of shares to lock + * @notice Locks assets to the exit queue. The shares to assets rate will be locked at the moment of the call. + * @param shares The number of shares to exit * @param receiver The address that will receive assets upon withdrawal * @return positionTicket The position ticket of the exit queue */ @@ -83,11 +72,12 @@ interface IVaultEnterExit is IVaultState { function getExitQueueIndex(uint256 positionTicket) external view returns (int256); /** - * @notice Calculates the number of shares and assets that can be claimed from the exit queue. + * @notice Calculates the number of assets that can be claimed from the exit queue. * @param receiver The address that will receive assets upon withdrawal * @param positionTicket The exit queue ticket received after the `enterExitQueue` call - * @param timestamp The timestamp when the shares entered the exit queue - * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`. + * @param timestamp The timestamp when the assets entered the exit queue + * @param exitQueueIndex The exit queue index at which the shares were burned. + * It can be looked up by calling `getExitQueueIndex`. Only relevant for V1 positions, otherwise pass 0. * @return leftShares The number of shares that are still in the queue * @return claimedShares The number of claimed shares * @return claimedAssets The number of claimed assets @@ -102,23 +92,13 @@ interface IVaultEnterExit is IVaultState { /** * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`. * @param positionTicket The exit queue ticket received after the `enterExitQueue` call - * @param timestamp The timestamp when the shares entered the exit queue - * @param exitQueueIndex The exit queue index at which the shares were burned. It can be looked up by calling `getExitQueueIndex`. - * @return newPositionTicket The new exit queue ticket in case not all the shares were burned. Otherwise 0. - * @return claimedShares The number of shares claimed - * @return claimedAssets The number of assets claimed + * @param timestamp The timestamp when the assets entered the exit queue + * @param exitQueueIndex The exit queue index at which the shares were burned. + * It can be looked up by calling `getExitQueueIndex`. Only relevant for V1 positions, otherwise pass 0. */ function claimExitedAssets( uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex - ) external returns (uint256 newPositionTicket, uint256 claimedShares, uint256 claimedAssets); - - /** - * @notice Redeems assets from the Vault by utilising what has not been staked yet. Can only be called when vault is not collateralized. - * @param shares The number of shares to burn - * @param receiver The address that will receive assets - * @return assets The number of assets withdrawn - */ - function redeem(uint256 shares, address receiver) external returns (uint256 assets); + ) external; } diff --git a/contracts/interfaces/IVaultState.sol b/contracts/interfaces/IVaultState.sol index 1223f87a..e7cfae3b 100644 --- a/contracts/interfaces/IVaultState.sol +++ b/contracts/interfaces/IVaultState.sol @@ -12,7 +12,7 @@ import {IVaultFee} from './IVaultFee.sol'; */ interface IVaultState is IVaultFee { /** - * @notice Event emitted on checkpoint creation + * @notice Event emitted on checkpoint creation (V1 exit queue) * @param shares The number of burned shares * @param assets The amount of exited assets */ @@ -51,10 +51,10 @@ interface IVaultState is IVaultFee { function withdrawableAssets() external view returns (uint256); /** - * @notice Queued Shares - * @return The total number of shares queued for exit + * @notice Total Exiting Assets + * @return The total number of assets queued for exit */ - function queuedShares() external view returns (uint128); + function totalExitingAssets() external view returns (uint128); /** * @notice Returns the number of shares held by an account diff --git a/contracts/libraries/Errors.sol b/contracts/libraries/Errors.sol index 21b230ad..871c3544 100644 --- a/contracts/libraries/Errors.sol +++ b/contracts/libraries/Errors.sol @@ -20,7 +20,6 @@ library Errors { error InvalidFeePercent(); error NotHarvested(); error NotCollateralized(); - error Collateralized(); error InvalidProof(); error LowLtv(); error RedemptionExceeded(); @@ -32,7 +31,6 @@ library Errors { error UpgradeFailed(); error InvalidValidator(); error InvalidValidators(); - error WhitelistAlreadyUpdated(); error DeadlineExpired(); error PermitInvalidSigner(); error InvalidValidatorsRegistryRoot(); @@ -53,5 +51,5 @@ library Errors { error InvalidCheckpointIndex(); error InvalidCheckpointValue(); error MaxOraclesExceeded(); - error ClaimTooEarly(); + error ExitRequestNotProcessed(); } diff --git a/contracts/libraries/ExitQueue.sol b/contracts/libraries/ExitQueue.sol index 6633c84d..b638e131 100644 --- a/contracts/libraries/ExitQueue.sol +++ b/contracts/libraries/ExitQueue.sol @@ -30,6 +30,21 @@ library ExitQueue { Checkpoint[] checkpoints; } + /** + * @notice Check whether the position is a V1 position + * @param self An array containing checkpoints + * @param queuedShares The number of shares that are queued for exiting + * @param positionTicket The position ticket to check + * @return true if the position is a V1 position, false otherwise + */ + function isV1Position( + History storage self, + uint256 queuedShares, + uint256 positionTicket + ) internal view returns (bool) { + return positionTicket < getLatestTotalTickets(self) + queuedShares; + } + /** * @notice Get the latest checkpoint total tickets * @param self An array containing checkpoints diff --git a/contracts/misc/RewardSplitter.sol b/contracts/misc/RewardSplitter.sol index b35a0c82..6b294f3f 100644 --- a/contracts/misc/RewardSplitter.sol +++ b/contracts/misc/RewardSplitter.sol @@ -133,12 +133,6 @@ contract RewardSplitter is IRewardSplitter, Initializable, OwnableUpgradeable, M return IVaultEnterExit(vault).enterExitQueue(rewards, receiver); } - /// @inheritdoc IRewardSplitter - function redeem(uint256 rewards, address receiver) external override returns (uint256 assets) { - _withdrawRewards(msg.sender, rewards); - return IVaultEnterExit(vault).redeem(rewards, receiver); - } - /// @inheritdoc IRewardSplitter function syncRewards() public override { // SLOAD to memory diff --git a/contracts/mocks/EthPrivVaultV2Mock.sol b/contracts/mocks/EthPrivVaultV3Mock.sol similarity index 90% rename from contracts/mocks/EthPrivVaultV2Mock.sol rename to contracts/mocks/EthPrivVaultV3Mock.sol index 5f8bfc8b..32a7df19 100644 --- a/contracts/mocks/EthPrivVaultV2Mock.sol +++ b/contracts/mocks/EthPrivVaultV3Mock.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.22; import {EthPrivVault} from '../vaults/ethereum/EthPrivVault.sol'; -contract EthPrivVaultV2Mock is EthPrivVault { +contract EthPrivVaultV3Mock is EthPrivVault { uint128 public newVar; /// @custom:oz-upgrades-unsafe-allow constructor @@ -28,7 +28,7 @@ contract EthPrivVaultV2Mock is EthPrivVault { ) {} - function initialize(bytes calldata data) external payable virtual override reinitializer(2) { + function initialize(bytes calldata data) external payable virtual override reinitializer(3) { (newVar) = abi.decode(data, (uint128)); } @@ -37,6 +37,6 @@ contract EthPrivVaultV2Mock is EthPrivVault { } function version() public pure virtual override returns (uint8) { - return 2; + return 3; } } diff --git a/contracts/mocks/EthVaultV3Mock.sol b/contracts/mocks/EthVaultV3Mock.sol index f0c967d6..5e816610 100644 --- a/contracts/mocks/EthVaultV3Mock.sol +++ b/contracts/mocks/EthVaultV3Mock.sol @@ -2,9 +2,11 @@ pragma solidity =0.8.22; -import {EthVaultV2Mock} from './EthVaultV2Mock.sol'; +import {EthVault} from '../vaults/ethereum/EthVault.sol'; + +contract EthVaultV3Mock is EthVault { + uint128 public newVar; -contract EthVaultV3Mock is EthVaultV2Mock { /// @custom:oz-upgrades-unsafe-allow constructor constructor( address _keeper, @@ -15,7 +17,7 @@ contract EthVaultV3Mock is EthVaultV2Mock { address sharedMevEscrow, uint256 exitingAssetsClaimDelay ) - EthVaultV2Mock( + EthVault( _keeper, _vaultsRegistry, _validatorsRegistry, @@ -26,7 +28,13 @@ contract EthVaultV3Mock is EthVaultV2Mock { ) {} - function initialize(bytes calldata data) external payable override reinitializer(3) {} + function initialize(bytes calldata data) external payable virtual override reinitializer(3) { + (newVar) = abi.decode(data, (uint128)); + } + + function somethingNew() external pure returns (bool) { + return true; + } function version() public pure virtual override returns (uint8) { return 3; diff --git a/contracts/mocks/EthVaultV2Mock.sol b/contracts/mocks/EthVaultV4Mock.sol similarity index 61% rename from contracts/mocks/EthVaultV2Mock.sol rename to contracts/mocks/EthVaultV4Mock.sol index 0d5d0fba..085c687c 100644 --- a/contracts/mocks/EthVaultV2Mock.sol +++ b/contracts/mocks/EthVaultV4Mock.sol @@ -2,11 +2,9 @@ pragma solidity =0.8.22; -import {EthVault} from '../vaults/ethereum/EthVault.sol'; - -contract EthVaultV2Mock is EthVault { - uint128 public newVar; +import {EthVaultV3Mock} from './EthVaultV3Mock.sol'; +contract EthVaultV4Mock is EthVaultV3Mock { /// @custom:oz-upgrades-unsafe-allow constructor constructor( address _keeper, @@ -17,7 +15,7 @@ contract EthVaultV2Mock is EthVault { address sharedMevEscrow, uint256 exitingAssetsClaimDelay ) - EthVault( + EthVaultV3Mock( _keeper, _vaultsRegistry, _validatorsRegistry, @@ -28,15 +26,9 @@ contract EthVaultV2Mock is EthVault { ) {} - function initialize(bytes calldata data) external payable virtual override reinitializer(2) { - (newVar) = abi.decode(data, (uint128)); - } - - function somethingNew() external pure returns (bool) { - return true; - } + function initialize(bytes calldata data) external payable override reinitializer(4) {} function version() public pure virtual override returns (uint8) { - return 2; + return 4; } } diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol new file mode 100644 index 00000000..86cefbc3 --- /dev/null +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IEthBlocklistErc20Vault} from '../../interfaces/IEthBlocklistErc20Vault.sol'; +import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; +import {ERC20Upgradeable} from '../../base/ERC20Upgradeable.sol'; +import {VaultEthStaking, IVaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {VaultBlocklist} from '../modules/VaultBlocklist.sol'; +import {EthErc20Vault, IEthErc20Vault} from './EthErc20Vault.sol'; + +/** + * @title EthBlocklistErc20Vault + * @author StakeWise + * @notice Defines the Ethereum staking Vault with blocking and ERC-20 functionality + */ +contract EthBlocklistErc20Vault is + Initializable, + EthErc20Vault, + VaultBlocklist, + IEthBlocklistErc20Vault +{ + uint8 private constant _version = 2; + + /** + * @dev Constructor + * @dev Since the immutable variable value is stored in the bytecode, + * its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage. + * @param _keeper The address of the Keeper contract + * @param _vaultsRegistry The address of the VaultsRegistry contract + * @param _validatorsRegistry The contract address used for registering validators in beacon chain + * @param osTokenVaultController The address of the OsTokenVaultController contract + * @param osTokenConfig The address of the OsTokenConfig contract + * @param sharedMevEscrow The address of the shared MEV escrow + * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + uint256 exitingAssetsClaimDelay + ) + EthErc20Vault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IEthErc20Vault + function initialize( + bytes calldata params + ) external payable virtual override(IEthErc20Vault, EthErc20Vault) reinitializer(_version) { + // initialize deployed vault + address _admin = IEthVaultFactory(msg.sender).vaultAdmin(); + __EthErc20Vault_init( + _admin, + IEthVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (EthErc20VaultInitParams)) + ); + // blocklist manager is initially set to admin address + __VaultBlocklist_init(_admin); + __EthErc20Vault_initV2(); + } + + /// @inheritdoc IVaultEthStaking + function deposit( + address receiver, + address referrer + ) public payable virtual override(IVaultEthStaking, VaultEthStaking) returns (uint256 shares) { + _checkBlocklist(msg.sender); + _checkBlocklist(receiver); + return super.deposit(receiver, referrer); + } + + /** + * @dev Function for depositing using fallback function + */ + receive() external payable virtual override { + _checkBlocklist(msg.sender); + _deposit(msg.sender, msg.value, address(0)); + } + + /// @inheritdoc IVaultOsToken + function mintOsToken( + address receiver, + uint256 osTokenShares, + address referrer + ) public virtual override(IVaultOsToken, VaultOsToken) returns (uint256 assets) { + _checkBlocklist(msg.sender); + return super.mintOsToken(receiver, osTokenShares, referrer); + } + + /// @inheritdoc IEthBlocklistErc20Vault + function ejectUser(address user) external override { + // add user to the blocklist + updateBlocklist(user, true); + + // fetch shares of the user + uint256 userShares = _balances[user]; + if (userShares == 0) return; + + // calculated shares that are locked due to minted osToken + uint256 lockedShares = _getLockedShares(user); + if (lockedShares >= userShares) return; + + // calculate shares to eject + uint256 ejectedShares; + unchecked { + // cannot underflow as lockedShares < userShares + ejectedShares = userShares - lockedShares; + } + + // eject shares that are not locked + _enterExitQueue(user, ejectedShares, user); + } + + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { + return keccak256('EthBlocklistErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { + return _version; + } + + /// @inheritdoc ERC20Upgradeable + function _transfer(address from, address to, uint256 amount) internal virtual override { + _checkBlocklist(from); + _checkBlocklist(to); + super._transfer(from, to, amount); + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol new file mode 100644 index 00000000..cac02670 --- /dev/null +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IEthBlocklistVault} from '../../interfaces/IEthBlocklistVault.sol'; +import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultEthStaking, IVaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {VaultBlocklist} from '../modules/VaultBlocklist.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {EthVault, IEthVault} from './EthVault.sol'; + +/** + * @title EthBlocklistVault + * @author StakeWise + * @notice Defines the Ethereum staking Vault with blocking addresses functionality + */ +contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlocklistVault { + uint8 private constant _version = 2; + + /** + * @dev Constructor + * @dev Since the immutable variable value is stored in the bytecode, + * its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage. + * @param _keeper The address of the Keeper contract + * @param _vaultsRegistry The address of the VaultsRegistry contract + * @param _validatorsRegistry The contract address used for registering validators in beacon chain + * @param osTokenVaultController The address of the OsTokenVaultController contract + * @param osTokenConfig The address of the OsTokenConfig contract + * @param sharedMevEscrow The address of the shared MEV escrow + * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + uint256 exitingAssetsClaimDelay + ) + EthVault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IEthVault + function initialize( + bytes calldata params + ) external payable virtual override(IEthVault, EthVault) reinitializer(_version) { + // initialize deployed vault + address _admin = IEthVaultFactory(msg.sender).vaultAdmin(); + __EthVault_init( + _admin, + IEthVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (EthVaultInitParams)) + ); + // blocklist manager is initially set to admin address + __VaultBlocklist_init(_admin); + __EthVault_initV2(); + } + + /// @inheritdoc IVaultEthStaking + function deposit( + address receiver, + address referrer + ) public payable virtual override(IVaultEthStaking, VaultEthStaking) returns (uint256 shares) { + _checkBlocklist(msg.sender); + _checkBlocklist(receiver); + return super.deposit(receiver, referrer); + } + + /** + * @dev Function for depositing using fallback function + */ + receive() external payable virtual override { + _checkBlocklist(msg.sender); + _deposit(msg.sender, msg.value, address(0)); + } + + /// @inheritdoc IVaultOsToken + function mintOsToken( + address receiver, + uint256 osTokenShares, + address referrer + ) public virtual override(IVaultOsToken, VaultOsToken) returns (uint256 assets) { + _checkBlocklist(msg.sender); + return super.mintOsToken(receiver, osTokenShares, referrer); + } + + /// @inheritdoc IEthBlocklistVault + function ejectUser(address user) external override { + // add user to blocklist + updateBlocklist(user, true); + + // fetch shares of the user + uint256 userShares = _balances[user]; + if (userShares == 0) return; + + // calculated shares that are locked due to minted osToken + uint256 lockedShares = _getLockedShares(user); + if (lockedShares >= userShares) return; + + // calculate shares to eject + uint256 ejectedShares; + unchecked { + // cannot underflow as lockedShares < userShares + ejectedShares = userShares - lockedShares; + } + + // eject shares that are not locked + _enterExitQueue(user, ejectedShares, user); + } + + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, EthVault) returns (bytes32) { + return keccak256('EthBlocklistVault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, EthVault) returns (uint8) { + return _version; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/vaults/ethereum/EthErc20Vault.sol b/contracts/vaults/ethereum/EthErc20Vault.sol index 893ff7fd..19226156 100644 --- a/contracts/vaults/ethereum/EthErc20Vault.sol +++ b/contracts/vaults/ethereum/EthErc20Vault.sol @@ -3,9 +3,6 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; -import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; -import {IVaultEnterExit} from '../../interfaces/IVaultEnterExit.sol'; -import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; import {IEthErc20Vault} from '../../interfaces/IEthErc20Vault.sol'; import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; @@ -14,10 +11,10 @@ import {ERC20Upgradeable} from '../../base/ERC20Upgradeable.sol'; import {VaultValidators} from '../modules/VaultValidators.sol'; import {VaultAdmin} from '../modules/VaultAdmin.sol'; import {VaultFee} from '../modules/VaultFee.sol'; -import {VaultVersion} from '../modules/VaultVersion.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; import {VaultImmutables} from '../modules/VaultImmutables.sol'; import {VaultState} from '../modules/VaultState.sol'; -import {VaultEnterExit} from '../modules/VaultEnterExit.sol'; +import {VaultEnterExit, IVaultEnterExit} from '../modules/VaultEnterExit.sol'; import {VaultOsToken} from '../modules/VaultOsToken.sol'; import {VaultEthStaking} from '../modules/VaultEthStaking.sol'; import {VaultMev} from '../modules/VaultMev.sol'; @@ -44,6 +41,8 @@ contract EthErc20Vault is Multicall, IEthErc20Vault { + uint8 private constant _version = 2; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -75,7 +74,15 @@ contract EthErc20Vault is } /// @inheritdoc IEthErc20Vault - function initialize(bytes calldata params) external payable virtual override initializer { + function initialize( + bytes calldata params + ) external payable virtual override reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthErc20Vault_initV2(); + return; + } + // initialize deployed vault __EthErc20Vault_init( IEthVaultFactory(msg.sender).vaultAdmin(), IEthVaultFactory(msg.sender).ownMevEscrow(), @@ -104,19 +111,6 @@ contract EthErc20Vault is return success; } - /// @inheritdoc IVaultEnterExit - function redeem( - uint256 shares, - address receiver - ) - public - virtual - override(IVaultEnterExit, VaultEnterExit, VaultOsToken) - returns (uint256 assets) - { - return super.redeem(shares, receiver); - } - /// @inheritdoc IVaultEnterExit function enterExitQueue( uint256 shares, @@ -127,8 +121,7 @@ contract EthErc20Vault is override(IVaultEnterExit, VaultEnterExit, VaultOsToken) returns (uint256 positionTicket) { - positionTicket = super.enterExitQueue(shares, receiver); - emit Transfer(msg.sender, address(this), shares); + return super.enterExitQueue(shares, receiver); } /// @inheritdoc IVaultVersion @@ -138,17 +131,7 @@ contract EthErc20Vault is /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { - return 1; - } - - /// @inheritdoc VaultState - function _updateExitQueue() - internal - virtual - override(VaultState, VaultToken) - returns (uint256 burnedShares) - { - return super._updateExitQueue(); + return _version; } /// @inheritdoc VaultState @@ -188,6 +171,13 @@ contract EthErc20Vault is __VaultEthStaking_init(); } + /** + * @dev Initializes the EthErc20Vault V2 contract + */ + function __EthErc20Vault_initV2() internal onlyInitializing { + __VaultState_initV2(); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index a806c474..f502a769 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -5,9 +5,7 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; -import {IEthVault} from '../../interfaces/IEthVault.sol'; import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; -import {IVaultState} from '../../interfaces/IVaultState.sol'; import {IPoolEscrow} from '../../interfaces/IPoolEscrow.sol'; import {IEthGenesisVault} from '../../interfaces/IEthGenesisVault.sol'; import {IRewardEthToken} from '../../interfaces/IRewardEthToken.sol'; @@ -16,8 +14,8 @@ import {Errors} from '../../libraries/Errors.sol'; import {VaultValidators} from '../modules/VaultValidators.sol'; import {VaultEnterExit} from '../modules/VaultEnterExit.sol'; import {VaultEthStaking} from '../modules/VaultEthStaking.sol'; -import {VaultState} from '../modules/VaultState.sol'; -import {EthVault} from './EthVault.sol'; +import {VaultState, IVaultState} from '../modules/VaultState.sol'; +import {EthVault, IEthVault} from './EthVault.sol'; /** * @title EthGenesisVault @@ -25,6 +23,8 @@ import {EthVault} from './EthVault.sol'; * @notice Defines the Genesis Vault for Ethereum staking migrated from StakeWise v2 */ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { + uint8 private constant _version = 2; + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IPoolEscrow private immutable _poolEscrow; @@ -76,15 +76,21 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { /// @inheritdoc IEthVault function initialize( bytes calldata params - ) external payable virtual override(IEthVault, EthVault) initializer { - (address admin, EthVaultInitParams memory initParams) = abi.decode( + ) external payable virtual override(IEthVault, EthVault) reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthVault_initV2(); + return; + } + // initialize deployed vault + (address _admin, EthVaultInitParams memory initParams) = abi.decode( params, (address, EthVaultInitParams) ); // use shared MEV escrow - __EthVault_init(admin, address(0), initParams); + __EthVault_init(_admin, address(0), initParams); emit GenesisVaultCreated( - admin, + _admin, initParams.capacity, initParams.feePercent, initParams.metadataIpfsHash @@ -104,7 +110,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, EthVault) returns (uint8) { - return 1; + return _version; } /// @inheritdoc IVaultState diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index abe179c1..f85d4d71 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -3,16 +3,14 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; -import {IEthErc20Vault} from '../../interfaces/IEthErc20Vault.sol'; import {IEthPrivErc20Vault} from '../../interfaces/IEthPrivErc20Vault.sol'; -import {IVaultEthStaking} from '../../interfaces/IVaultEthStaking.sol'; -import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; -import {Errors} from '../../libraries/Errors.sol'; -import {VaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {ERC20Upgradeable} from '../../base/ERC20Upgradeable.sol'; +import {VaultEthStaking, IVaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; import {VaultWhitelist} from '../modules/VaultWhitelist.sol'; -import {VaultVersion} from '../modules/VaultVersion.sol'; -import {EthErc20Vault} from './EthErc20Vault.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {EthErc20Vault, IEthErc20Vault} from './EthErc20Vault.sol'; /** * @title EthPrivErc20Vault @@ -20,6 +18,8 @@ import {EthErc20Vault} from './EthErc20Vault.sol'; * @notice Defines the Ethereum staking Vault with whitelist and ERC-20 token */ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEthPrivErc20Vault { + uint8 private constant _version = 2; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -56,25 +56,21 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth /// @inheritdoc IEthErc20Vault function initialize( bytes calldata params - ) external payable virtual override(IEthErc20Vault, EthErc20Vault) initializer { - address admin = IEthVaultFactory(msg.sender).vaultAdmin(); + ) external payable virtual override(IEthErc20Vault, EthErc20Vault) reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthErc20Vault_initV2(); + return; + } + // initialize deployed vault + address _admin = IEthVaultFactory(msg.sender).vaultAdmin(); __EthErc20Vault_init( - admin, + _admin, IEthVaultFactory(msg.sender).ownMevEscrow(), abi.decode(params, (EthErc20VaultInitParams)) ); // whitelister is initially set to admin address - __VaultWhitelist_init(admin); - } - - /// @inheritdoc IVaultVersion - function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { - return keccak256('EthPrivErc20Vault'); - } - - /// @inheritdoc IVaultVersion - function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { - return 1; + __VaultWhitelist_init(_admin); } /// @inheritdoc IVaultEthStaking @@ -82,9 +78,8 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth address receiver, address referrer ) public payable virtual override(IVaultEthStaking, VaultEthStaking) returns (uint256 shares) { - if (!(whitelistedAccounts[msg.sender] && whitelistedAccounts[receiver])) { - revert Errors.AccessDenied(); - } + _checkWhitelist(msg.sender); + _checkWhitelist(receiver); return super.deposit(receiver, referrer); } @@ -92,10 +87,61 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth * @dev Function for depositing using fallback function */ receive() external payable virtual override { - if (!whitelistedAccounts[msg.sender]) revert Errors.AccessDenied(); + _checkWhitelist(msg.sender); _deposit(msg.sender, msg.value, address(0)); } + /// @inheritdoc IVaultOsToken + function mintOsToken( + address receiver, + uint256 osTokenShares, + address referrer + ) public virtual override(IVaultOsToken, VaultOsToken) returns (uint256 assets) { + _checkWhitelist(msg.sender); + return super.mintOsToken(receiver, osTokenShares, referrer); + } + + /// @inheritdoc IEthPrivErc20Vault + function ejectUser(address user) external override { + // remove user from the whitelist + updateWhitelist(user, false); + + // fetch shares of the user + uint256 userShares = _balances[user]; + if (userShares == 0) return; + + // calculated shares that are locked due to minted osToken + uint256 lockedShares = _getLockedShares(user); + if (lockedShares >= userShares) return; + + // calculate shares to eject + uint256 ejectedShares; + unchecked { + // cannot underflow as lockedShares < userShares + ejectedShares = userShares - lockedShares; + } + + // eject shares that are not locked + _enterExitQueue(user, ejectedShares, user); + } + + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { + return keccak256('EthPrivErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { + return _version; + } + + /// @inheritdoc ERC20Upgradeable + function _transfer(address from, address to, uint256 amount) internal virtual override { + _checkWhitelist(from); + _checkWhitelist(to); + super._transfer(from, to, amount); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index 2cd9607b..9d8e014f 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -3,16 +3,13 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; -import {IEthVault} from '../../interfaces/IEthVault.sol'; import {IEthPrivVault} from '../../interfaces/IEthPrivVault.sol'; import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; -import {IVaultEthStaking} from '../../interfaces/IVaultEthStaking.sol'; -import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; -import {Errors} from '../../libraries/Errors.sol'; -import {VaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {VaultEthStaking, IVaultEthStaking} from '../modules/VaultEthStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; import {VaultWhitelist} from '../modules/VaultWhitelist.sol'; -import {VaultVersion} from '../modules/VaultVersion.sol'; -import {EthVault} from './EthVault.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {EthVault, IEthVault} from './EthVault.sol'; /** * @title EthPrivVault @@ -20,6 +17,8 @@ import {EthVault} from './EthVault.sol'; * @notice Defines the Ethereum staking Vault with whitelist */ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault { + uint8 private constant _version = 2; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -56,15 +55,21 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault /// @inheritdoc IEthVault function initialize( bytes calldata params - ) external payable virtual override(IEthVault, EthVault) initializer { - address admin = IEthVaultFactory(msg.sender).vaultAdmin(); + ) external payable virtual override(IEthVault, EthVault) reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthVault_initV2(); + return; + } + // initialize deployed vault + address _admin = IEthVaultFactory(msg.sender).vaultAdmin(); __EthVault_init( - admin, + _admin, IEthVaultFactory(msg.sender).ownMevEscrow(), abi.decode(params, (EthVaultInitParams)) ); // whitelister is initially set to admin address - __VaultWhitelist_init(admin); + __VaultWhitelist_init(_admin); } /// @inheritdoc IVaultEthStaking @@ -72,9 +77,8 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault address receiver, address referrer ) public payable virtual override(IVaultEthStaking, VaultEthStaking) returns (uint256 shares) { - if (!(whitelistedAccounts[msg.sender] && whitelistedAccounts[receiver])) { - revert Errors.AccessDenied(); - } + _checkWhitelist(msg.sender); + _checkWhitelist(receiver); return super.deposit(receiver, referrer); } @@ -82,10 +86,44 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault * @dev Function for depositing using fallback function */ receive() external payable virtual override { - if (!whitelistedAccounts[msg.sender]) revert Errors.AccessDenied(); + _checkWhitelist(msg.sender); _deposit(msg.sender, msg.value, address(0)); } + /// @inheritdoc IVaultOsToken + function mintOsToken( + address receiver, + uint256 osTokenShares, + address referrer + ) public virtual override(IVaultOsToken, VaultOsToken) returns (uint256 assets) { + _checkWhitelist(msg.sender); + return super.mintOsToken(receiver, osTokenShares, referrer); + } + + /// @inheritdoc IEthPrivVault + function ejectUser(address user) external override { + // remove user from the whitelist + updateWhitelist(user, false); + + // fetch shares of the user + uint256 userShares = _balances[user]; + if (userShares == 0) return; + + // calculated shares that are locked due to minted osToken + uint256 lockedShares = _getLockedShares(user); + if (lockedShares >= userShares) return; + + // calculate shares to eject + uint256 ejectedShares; + unchecked { + // cannot underflow as lockedShares < userShares + ejectedShares = userShares - lockedShares; + } + + // eject shares that are not locked + _enterExitQueue(user, ejectedShares, user); + } + /// @inheritdoc IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthVault) returns (bytes32) { return keccak256('EthPrivVault'); @@ -93,7 +131,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, EthVault) returns (uint8) { - return 1; + return _version; } /** diff --git a/contracts/vaults/ethereum/EthVault.sol b/contracts/vaults/ethereum/EthVault.sol index edf378d3..1b609ba2 100644 --- a/contracts/vaults/ethereum/EthVault.sol +++ b/contracts/vaults/ethereum/EthVault.sol @@ -3,18 +3,16 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; -import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; -import {IVaultEnterExit} from '../../interfaces/IVaultEnterExit.sol'; import {IEthVault} from '../../interfaces/IEthVault.sol'; import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; import {Multicall} from '../../base/Multicall.sol'; import {VaultValidators} from '../modules/VaultValidators.sol'; import {VaultAdmin} from '../modules/VaultAdmin.sol'; import {VaultFee} from '../modules/VaultFee.sol'; -import {VaultVersion} from '../modules/VaultVersion.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; import {VaultImmutables} from '../modules/VaultImmutables.sol'; import {VaultState} from '../modules/VaultState.sol'; -import {VaultEnterExit} from '../modules/VaultEnterExit.sol'; +import {VaultEnterExit, IVaultEnterExit} from '../modules/VaultEnterExit.sol'; import {VaultOsToken} from '../modules/VaultOsToken.sol'; import {VaultEthStaking} from '../modules/VaultEthStaking.sol'; import {VaultMev} from '../modules/VaultMev.sol'; @@ -39,6 +37,8 @@ contract EthVault is Multicall, IEthVault { + uint8 private constant _version = 2; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -70,7 +70,15 @@ contract EthVault is } /// @inheritdoc IEthVault - function initialize(bytes calldata params) external payable virtual override initializer { + function initialize( + bytes calldata params + ) external payable virtual override reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthVault_initV2(); + return; + } + // initialize deployed vault __EthVault_init( IEthVaultFactory(msg.sender).vaultAdmin(), IEthVaultFactory(msg.sender).ownMevEscrow(), @@ -78,19 +86,6 @@ contract EthVault is ); } - /// @inheritdoc IVaultEnterExit - function redeem( - uint256 shares, - address receiver - ) - public - virtual - override(IVaultEnterExit, VaultEnterExit, VaultOsToken) - returns (uint256 assets) - { - return super.redeem(shares, receiver); - } - /// @inheritdoc IVaultEnterExit function enterExitQueue( uint256 shares, @@ -111,7 +106,7 @@ contract EthVault is /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { - return 1; + return _version; } /** @@ -134,6 +129,13 @@ contract EthVault is __VaultEthStaking_init(); } + /** + * @dev Initializes the EthVault V2 contract + */ + function __EthVault_initV2() internal onlyInitializing { + __VaultState_initV2(); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/ethereum/custom/EthFoxVault.sol b/contracts/vaults/ethereum/custom/EthFoxVault.sol index 7854ff71..1538fe56 100644 --- a/contracts/vaults/ethereum/custom/EthFoxVault.sol +++ b/contracts/vaults/ethereum/custom/EthFoxVault.sol @@ -36,6 +36,8 @@ contract EthFoxVault is Multicall, IEthFoxVault { + uint8 private constant _version = 2; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -62,7 +64,15 @@ contract EthFoxVault is } /// @inheritdoc IEthFoxVault - function initialize(bytes calldata params) external payable virtual override initializer { + function initialize( + bytes calldata params + ) external payable virtual override reinitializer(_version) { + // if admin is already set, it's an upgrade + if (admin != address(0)) { + __EthFoxVault_initV2(); + return; + } + // initialize deployed vault EthFoxVaultInitParams memory initParams = abi.decode(params, (EthFoxVaultInitParams)); __EthFoxVault_init(initParams); emit EthFoxVaultCreated( @@ -93,14 +103,9 @@ contract EthFoxVault is uint256 userShares = _balances[user]; if (userShares == 0) return; - if (_isCollateralized()) { - // send user shares to exit queue - _enterExitQueue(user, userShares, user); - } else { - // redeem user shares - _redeem(user, userShares, user); - } - emit UserEjected(user, userShares); + // send user shares to exit queue + _enterExitQueue(user, userShares, user); + emit UserEjected(user, userShares); } /** @@ -118,7 +123,7 @@ contract EthFoxVault is /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { - return 1; + return _version; } /** @@ -137,6 +142,13 @@ contract EthFoxVault is __VaultEthStaking_init(); } + /** + * @dev Initializes the EthFoxVault V2 contract + */ + function __EthFoxVault_initV2() internal onlyInitializing { + __VaultState_initV2(); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/modules/VaultAdmin.sol b/contracts/vaults/modules/VaultAdmin.sol index e8a445dd..6e3c170f 100644 --- a/contracts/vaults/modules/VaultAdmin.sol +++ b/contracts/vaults/modules/VaultAdmin.sol @@ -29,6 +29,7 @@ abstract contract VaultAdmin is Initializable, IVaultAdmin { address _admin, string memory metadataIpfsHash ) internal onlyInitializing { + if (_admin == address(0)) revert Errors.ZeroAddress(); admin = _admin; emit MetadataUpdated(msg.sender, metadataIpfsHash); } diff --git a/contracts/vaults/modules/VaultEnterExit.sol b/contracts/vaults/modules/VaultEnterExit.sol index e7210141..523624eb 100644 --- a/contracts/vaults/modules/VaultEnterExit.sol +++ b/contracts/vaults/modules/VaultEnterExit.sol @@ -36,16 +36,13 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, /// @inheritdoc IVaultEnterExit function getExitQueueIndex(uint256 positionTicket) external view override returns (int256) { - uint256 checkpointIdx = _exitQueue.getCheckpointIndex(positionTicket); - return checkpointIdx < _exitQueue.checkpoints.length ? int256(checkpointIdx) : -1; - } - - /// @inheritdoc IVaultEnterExit - function redeem( - uint256 shares, - address receiver - ) public virtual override returns (uint256 assets) { - return _redeem(msg.sender, shares, receiver); + if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + uint256 checkpointIdx = _exitQueue.getCheckpointIndex(positionTicket); + return checkpointIdx < _exitQueue.checkpoints.length ? int256(checkpointIdx) : -1; + } + // calculate total exited tickets + uint256 totalExitedTickets = _totalExitedTickets + _getTotalExitableTickets(); + return (totalExitedTickets > positionTicket) ? int256(0) : -1; } /// @inheritdoc IVaultEnterExit @@ -66,19 +63,26 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, public view override - returns (uint256 leftShares, uint256 claimedShares, uint256 claimedAssets) + returns (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets) { - uint256 requestedShares = _exitRequests[ + uint256 exitingTickets = _exitRequests[ keccak256(abi.encode(receiver, timestamp, positionTicket)) ]; - - // calculate exited shares and assets - (claimedShares, claimedAssets) = _exitQueue.calculateExitedAssets( - exitQueueIndex, - positionTicket, - requestedShares - ); - leftShares = requestedShares - claimedShares; + if (exitingTickets == 0) return (0, 0, 0); + if (block.timestamp < timestamp + _exitingAssetsClaimDelay) return (exitingTickets, 0, 0); + + if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + // calculate exited assets in V1 exit queue + (exitedTickets, exitedAssets) = _exitQueue.calculateExitedAssets( + exitQueueIndex, + positionTicket, + exitingTickets + ); + } else { + // calculate exited assets + (exitedTickets, exitedAssets) = _calculateExitedTickets(exitingTickets, positionTicket); + } + leftTickets = exitingTickets - exitedTickets; } /// @inheritdoc IVaultEnterExit @@ -86,39 +90,58 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex - ) - external - override - returns (uint256 newPositionTicket, uint256 claimedShares, uint256 claimedAssets) - { - if (block.timestamp < timestamp + _exitingAssetsClaimDelay) revert Errors.ClaimTooEarly(); - bytes32 queueId = keccak256(abi.encode(msg.sender, timestamp, positionTicket)); - - // calculate exited shares and assets - uint256 leftShares; - (leftShares, claimedShares, claimedAssets) = calculateExitedAssets( + ) external override { + // calculate exited tickets and assets + (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets) = calculateExitedAssets( msg.sender, positionTicket, timestamp, exitQueueIndex ); - // nothing to claim - if (claimedShares == 0) return (positionTicket, claimedShares, claimedAssets); + if (exitedTickets == 0 || exitedAssets == 0) revert Errors.ExitRequestNotProcessed(); + + if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + // update unclaimed assets + _unclaimedAssets -= SafeCast.toUint128(exitedAssets); + } else { + // vault must be harvested to calculate exact withdrawable amount + _checkHarvested(); + + // update state + totalExitingAssets -= SafeCast.toUint128(exitedAssets); + _totalExitingTickets -= SafeCast.toUint128(exitedTickets); + _totalExitedTickets += exitedTickets; + } // clean up current exit request - delete _exitRequests[queueId]; + delete _exitRequests[keccak256(abi.encode(msg.sender, timestamp, positionTicket))]; - // skip creating new position for the shares rounding error - if (leftShares > 1) { + // skip creating new position for the tickets rounding error + uint256 newPositionTicket; + if (leftTickets > 1) { // update user's queue position - newPositionTicket = positionTicket + claimedShares; - _exitRequests[keccak256(abi.encode(msg.sender, timestamp, newPositionTicket))] = leftShares; + newPositionTicket = positionTicket + exitedTickets; + _exitRequests[keccak256(abi.encode(msg.sender, timestamp, newPositionTicket))] = leftTickets; } // transfer assets to the receiver - _unclaimedAssets -= SafeCast.toUint128(claimedAssets); - _transferVaultAssets(msg.sender, claimedAssets); - emit ExitedAssetsClaimed(msg.sender, positionTicket, newPositionTicket, claimedAssets); + _transferVaultAssets(msg.sender, exitedAssets); + emit ExitedAssetsClaimed(msg.sender, newPositionTicket, exitedAssets); + } + + function _calculateExitedTickets( + uint256 exitingTickets, + uint256 positionTicket + ) private view returns (uint256 exitedTickets, uint256 exitedAssets) { + // calculate total exitable tickets + uint256 exitableTickets = _getTotalExitableTickets(); + // calculate total exited tickets + uint256 totalExitedTickets = _totalExitedTickets + exitableTickets; + if (totalExitedTickets <= positionTicket) return (0, 0); + + // calculate exited tickets and assets + exitedTickets = Math.min(exitingTickets, totalExitedTickets - positionTicket); + return (exitedTickets, _convertExitTicketsToAssets(exitedTickets)); } /** @@ -155,74 +178,70 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, } /** - * @dev Internal function that must be used to process user withdrawals before first validator registration + * @dev Internal function for sending user shares to the exit queue * @param user The address of the user - * @param shares The number of shares to redeem - * @param receiver The address that will receive the assets - * @return assets The total amount of assets withdrawn + * @param shares The number of shares to lock + * @param receiver The address that will receive assets upon withdrawal + * @return positionTicket The position ticket of the exit queue */ - function _redeem( + function _enterExitQueue( address user, uint256 shares, address receiver - ) internal returns (uint256 assets) { - _checkNotCollateralized(); + ) internal returns (uint256 positionTicket) { + _checkHarvested(); if (shares == 0) revert Errors.InvalidShares(); if (receiver == address(0)) revert Errors.ZeroAddress(); - // calculate amount of assets to burn - assets = convertToAssets(shares); + // calculate amount of assets to lock + uint256 assets = convertToAssets(shares); if (assets == 0) revert Errors.InvalidAssets(); - // reverts in case there are not enough withdrawable assets - if (assets > withdrawableAssets()) revert Errors.InsufficientAssets(); + // convert assets to exiting tickets + uint256 exitingTickets = _convertAssetsToExitTickets(assets); - // update total assets + // reduce total assets _totalAssets -= SafeCast.toUint128(assets); - // burn owner shares + // burn shares _burnShares(user, shares); - // transfer assets to the receiver - _transferVaultAssets(receiver, assets); - - emit Redeemed(user, receiver, assets, shares); - } - - /** - * @dev Internal function that must be used to process user withdrawals after first validator registration - * @param user The address of the user - * @param shares The number of shares to send to exit queue - * @param receiver The address that will receive the assets - * @return positionTicket The position ticket in the exit queue - */ - function _enterExitQueue( - address user, - uint256 shares, - address receiver - ) internal virtual returns (uint256 positionTicket) { - _checkCollateralized(); - if (shares == 0) revert Errors.InvalidShares(); - if (receiver == address(0)) revert Errors.ZeroAddress(); - // SLOAD to memory - uint256 _queuedShares = queuedShares; + uint256 totalExitingTickets = _totalExitingTickets; // calculate position ticket - positionTicket = _exitQueue.getLatestTotalTickets() + _queuedShares; + positionTicket = _totalExitedTickets + totalExitingTickets; + + // increase total exiting assets and tickets + totalExitingAssets += SafeCast.toUint128(assets); + _totalExitingTickets = SafeCast.toUint128(totalExitingTickets + exitingTickets); // add to the exit requests - _exitRequests[keccak256(abi.encode(receiver, block.timestamp, positionTicket))] = shares; + _exitRequests[ + keccak256(abi.encode(receiver, block.timestamp, positionTicket)) + ] = exitingTickets; - // reverts if owner does not have enough shares - _balances[user] -= shares; + emit ExitQueueEntered(user, receiver, positionTicket, assets); + } - unchecked { - // cannot overflow as it is capped with _totalShares - queuedShares = SafeCast.toUint128(_queuedShares + shares); + /** + * @dev Internal function for calculating the number of assets that can be withdrawn + * @return assets The number of assets that can be withdrawn + */ + function _getTotalExitableTickets() private view returns (uint256) { + // calculate available assets + uint256 availableAssets = _vaultAssets() - _unclaimedAssets; + uint256 queuedAssets = convertToAssets(_queuedShares); + if (queuedAssets > 0) { + unchecked { + // cannot underflow as availableAssets >= queuedV1Assets + availableAssets = availableAssets > queuedAssets ? availableAssets - queuedAssets : 0; + } } + if (availableAssets == 0) return 0; - emit ExitQueueEntered(user, receiver, positionTicket, shares); + // calculate number of tickets that can be withdrawn based on available assets + return _convertAssetsToExitTickets(Math.min(availableAssets, totalExitingAssets)); } /** diff --git a/contracts/vaults/modules/VaultImmutables.sol b/contracts/vaults/modules/VaultImmutables.sol index 70885dcf..8c347056 100644 --- a/contracts/vaults/modules/VaultImmutables.sol +++ b/contracts/vaults/modules/VaultImmutables.sol @@ -35,14 +35,6 @@ abstract contract VaultImmutables { _validatorsRegistry = validatorsRegistry; } - /** - * @dev Internal method for checking whether the vault is collateralized - * @return true if the vault is collateralized, false otherwise - */ - function _isCollateralized() internal view returns (bool) { - return IKeeperRewards(_keeper).isCollateralized(address(this)); - } - /** * @dev Internal method for checking whether the vault is harvested */ @@ -54,13 +46,6 @@ abstract contract VaultImmutables { * @dev Internal method for checking whether the vault is collateralized */ function _checkCollateralized() internal view { - if (!_isCollateralized()) revert Errors.NotCollateralized(); - } - - /** - * @dev Internal method for checking whether the vault is not collateralized - */ - function _checkNotCollateralized() internal view { - if (_isCollateralized()) revert Errors.Collateralized(); + if (!IKeeperRewards(_keeper).isCollateralized(address(this))) revert Errors.NotCollateralized(); } } diff --git a/contracts/vaults/modules/VaultOsToken.sol b/contracts/vaults/modules/VaultOsToken.sol index d69f00f9..827fb073 100644 --- a/contracts/vaults/modules/VaultOsToken.sol +++ b/contracts/vaults/modules/VaultOsToken.sol @@ -7,10 +7,9 @@ import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; import {IOsTokenVaultController} from '../../interfaces/IOsTokenVaultController.sol'; import {IOsTokenConfig} from '../../interfaces/IOsTokenConfig.sol'; import {IVaultOsToken} from '../../interfaces/IVaultOsToken.sol'; -import {IVaultEnterExit} from '../../interfaces/IVaultEnterExit.sol'; import {Errors} from '../../libraries/Errors.sol'; import {VaultImmutables} from './VaultImmutables.sol'; -import {VaultEnterExit} from './VaultEnterExit.sol'; +import {VaultEnterExit, IVaultEnterExit} from './VaultEnterExit.sol'; import {VaultState} from './VaultState.sol'; /** @@ -45,7 +44,7 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I } /// @inheritdoc IVaultOsToken - function osTokenPositions(address user) external view override returns (uint128 shares) { + function osTokenPositions(address user) public view override returns (uint128 shares) { OsTokenPosition memory position = _positions[user]; if (position.shares != 0) _syncPositionFee(position); return position.shares; @@ -56,7 +55,7 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I address receiver, uint256 osTokenShares, address referrer - ) external override returns (uint256 assets) { + ) public virtual override returns (uint256 assets) { _checkCollateralized(); _checkHarvested(); @@ -145,15 +144,6 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I emit OsTokenRedeemed(msg.sender, owner, receiver, osTokenShares, burnedShares, receivedAssets); } - /// @inheritdoc IVaultEnterExit - function redeem( - uint256 shares, - address receiver - ) public virtual override(IVaultEnterExit, VaultEnterExit) returns (uint256 assets) { - assets = super.redeem(shares, receiver); - _checkOsTokenPosition(msg.sender); - } - /// @inheritdoc IVaultEnterExit function enterExitQueue( uint256 shares, @@ -282,27 +272,40 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I } /** - * @notice Internal function for checking position validity. Reverts if it is invalid. + * @dev Internal function for retrieving the amount of locked shares for a given user. + * Reverts if the vault is not harvested. * @param user The address of the user + * @return The amount of locked shares */ - function _checkOsTokenPosition(address user) internal view { - // fetch user position - OsTokenPosition memory position = _positions[user]; - if (position.shares == 0) return; + function _getLockedShares(address user) internal view returns (uint256) { + uint256 osTokenShares = osTokenPositions(user); + if (osTokenShares == 0) return 0; + + // calculate locked assets + uint256 lockedAssets = Math.mulDiv( + _osTokenVaultController.convertToAssets(osTokenShares), + _maxPercent, + _osTokenConfig.ltvPercent() + ); + if (lockedAssets == 0) return 0; // check whether vault assets are up to date _checkHarvested(); - // sync fee - _syncPositionFee(position); + // convert to vault shares + return convertToShares(lockedAssets); + } - // calculate and validate position LTV - if ( - Math.mulDiv(convertToAssets(_balances[user]), _osTokenConfig.ltvPercent(), _maxPercent) < - _osTokenVaultController.convertToAssets(position.shares) - ) { - revert Errors.LowLtv(); - } + /** + * @notice Internal function for checking position validity + * @param user The address of the user + */ + function _checkOsTokenPosition(address user) internal view { + uint256 lockedShares = _getLockedShares(user); + if (lockedShares == 0) return; + + // validate position LTV + if (lockedShares > _balances[user]) revert Errors.LowLtv(); } /** diff --git a/contracts/vaults/modules/VaultState.sol b/contracts/vaults/modules/VaultState.sol index 64e38695..f04da2b2 100644 --- a/contracts/vaults/modules/VaultState.sol +++ b/contracts/vaults/modules/VaultState.sol @@ -23,8 +23,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint128 internal _totalShares; uint128 internal _totalAssets; - /// @inheritdoc IVaultState - uint128 public override queuedShares; + uint128 internal _queuedShares; uint128 internal _unclaimedAssets; ExitQueue.History internal _exitQueue; @@ -33,6 +32,10 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint256 private _capacity; + uint128 public override totalExitingAssets; + uint128 internal _totalExitingTickets; + uint256 internal _totalExitedTickets; + /// @inheritdoc IVaultState function totalShares() external view override returns (uint256) { return _totalShares; @@ -74,7 +77,9 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault unchecked { // calculate assets that are reserved by users who queued for exit // cannot overflow as it is capped with underlying asset total supply - uint256 reservedAssets = convertToAssets(queuedShares) + _unclaimedAssets; + uint256 reservedAssets = convertToAssets(_queuedShares) + + totalExitingAssets + + _unclaimedAssets; return vaultAssets > reservedAssets ? vaultAssets - reservedAssets : 0; } } @@ -106,11 +111,31 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault // SLOAD to memory uint256 newTotalAssets = _totalAssets; if (totalAssetsDelta < 0) { - // add penalty to total assets - newTotalAssets -= uint256(-totalAssetsDelta); + uint256 penalty = uint256(-totalAssetsDelta); + + // SLOAD to memory + uint256 _totalExitingAssets = totalExitingAssets; + // apply penalty to exiting assets + uint256 exitingAssetsPenalty = Math.mulDiv( + penalty, + _totalExitingAssets, + _totalExitingAssets + newTotalAssets + ); + + unchecked { + // cannot underflow as exitingAssetsPenalty <= penalty + penalty -= exitingAssetsPenalty; + } - // update state - _totalAssets = SafeCast.toUint128(newTotalAssets); + // subtract penalty from total assets (excludes exiting assets) + if (penalty > 0) { + _totalAssets = SafeCast.toUint128(newTotalAssets - penalty); + } + + // subtract penalty from total exiting assets + if (exitingAssetsPenalty > 0) { + totalExitingAssets = SafeCast.toUint128(_totalExitingAssets - exitingAssetsPenalty); + } return; } @@ -157,14 +182,14 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault */ function _updateExitQueue() internal virtual returns (uint256 burnedShares) { // SLOAD to memory - uint256 _queuedShares = queuedShares; - if (_queuedShares == 0) return 0; + uint256 queuedShares = _queuedShares; + if (queuedShares == 0) return 0; // calculate the amount of assets that can be exited uint256 unclaimedAssets = _unclaimedAssets; uint256 exitedAssets = Math.min( _vaultAssets() - unclaimedAssets, - convertToAssets(_queuedShares) + convertToAssets(queuedShares) ); if (exitedAssets == 0) return 0; @@ -173,7 +198,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault if (burnedShares == 0) return 0; // update queued shares and unclaimed assets - queuedShares = SafeCast.toUint128(_queuedShares - burnedShares); + _queuedShares = SafeCast.toUint128(queuedShares - burnedShares); _unclaimedAssets = SafeCast.toUint128(unclaimedAssets + exitedAssets); // push checkpoint so that exited assets could be claimed @@ -234,6 +259,30 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault : Math.mulDiv(assets, totalShares_, _totalAssets, rounding); } + /** + * @dev Internal conversion function (from assets to exit tickets) + */ + function _convertAssetsToExitTickets(uint256 assets) internal view returns (uint256 exitTickets) { + uint256 totalExitingTickets = _totalExitingTickets; + // Will revert if assets > 0, totalExitingTickets > 0 and totalExitingAssets = 0. + // That corresponds to a case where any asset would represent an infinite amount of tickets. + return + (assets == 0 || totalExitingTickets == 0) + ? assets + : Math.mulDiv(assets, totalExitingTickets, totalExitingAssets, Math.Rounding.Floor); + } + + /** + * @dev Internal conversion function (from exit tickets to assets) + */ + function _convertExitTicketsToAssets(uint256 exitTickets) internal view returns (uint256 assets) { + uint256 totalExitingTickets = _totalExitingTickets; + return + (totalExitingTickets == 0) + ? exitTickets + : Math.mulDiv(exitTickets, totalExitingAssets, totalExitingTickets); + } + /** * @dev Internal function for harvesting Vaults' new assets * @return The total assets delta after harvest @@ -260,10 +309,18 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault if (capacity_ != type(uint256).max) _capacity = capacity_; } + /** + * @dev Initializes the VaultState contract V2 + */ + function __VaultState_initV2() internal onlyInitializing { + // set initial value for total exited tickets + _totalExitedTickets = _exitQueue.getLatestTotalTickets() + _queuedShares; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[50] private __gap; + uint256[48] private __gap; } diff --git a/contracts/vaults/modules/VaultToken.sol b/contracts/vaults/modules/VaultToken.sol index 03ae52fe..7e95f666 100644 --- a/contracts/vaults/modules/VaultToken.sol +++ b/contracts/vaults/modules/VaultToken.sol @@ -37,12 +37,6 @@ abstract contract VaultToken is Initializable, ERC20Upgradeable, VaultState, IVa emit Transfer(owner, address(0), shares); } - /// @inheritdoc VaultState - function _updateExitQueue() internal virtual override returns (uint256 burnedShares) { - burnedShares = super._updateExitQueue(); - if (burnedShares != 0) emit Transfer(address(this), address(0), burnedShares); - } - /// @inheritdoc ERC20Upgradeable function _transfer(address from, address to, uint256 amount) internal virtual override { if (from == address(0) || to == address(0)) revert Errors.ZeroAddress(); diff --git a/contracts/vaults/modules/VaultWhitelist.sol b/contracts/vaults/modules/VaultWhitelist.sol index 3938035f..83aef0b8 100644 --- a/contracts/vaults/modules/VaultWhitelist.sol +++ b/contracts/vaults/modules/VaultWhitelist.sol @@ -20,9 +20,11 @@ abstract contract VaultWhitelist is Initializable, VaultAdmin, IVaultWhitelist { mapping(address => bool) public override whitelistedAccounts; /// @inheritdoc IVaultWhitelist - function updateWhitelist(address account, bool approved) external override { + function updateWhitelist(address account, bool approved) public override { if (msg.sender != whitelister) revert Errors.AccessDenied(); - _updateWhitelist(account, approved); + if (whitelistedAccounts[account] == approved) return; + whitelistedAccounts[account] = approved; + emit WhitelistUpdated(msg.sender, account, approved); } /// @inheritdoc IVaultWhitelist @@ -32,14 +34,11 @@ abstract contract VaultWhitelist is Initializable, VaultAdmin, IVaultWhitelist { } /** - * @notice Internal function for updating whitelist - * @param account The address of the account to update - * @param approved Defines whether account is added to the whitelist or removed + * @notice Internal function for checking whether account is in the whitelist + * @param account The address of the account to check */ - function _updateWhitelist(address account, bool approved) private { - if (whitelistedAccounts[account] == approved) revert Errors.WhitelistAlreadyUpdated(); - whitelistedAccounts[account] = approved; - emit WhitelistUpdated(msg.sender, account, approved); + function _checkWhitelist(address account) internal view { + if (!whitelistedAccounts[account]) revert Errors.AccessDenied(); } /** @@ -58,7 +57,6 @@ abstract contract VaultWhitelist is Initializable, VaultAdmin, IVaultWhitelist { */ function __VaultWhitelist_init(address _whitelister) internal onlyInitializing { _setWhitelister(_whitelister); - _updateWhitelist(_whitelister, true); } /** diff --git a/helpers/constants.ts b/helpers/constants.ts index 48785de7..08d55aca 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -14,7 +14,7 @@ export const NETWORKS: { governor: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', validatorsRegistry: '0x4242424242424242424242424242424242424242', securityDeposit: 1000000000n, // 1 gwei - exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours + exitedAssetsClaimDelay: 30 * 60 * 60, // 30 hours // Keeper oracles: [ @@ -76,7 +76,7 @@ export const NETWORKS: { governor: '0x144a98cb1CdBb23610501fE6108858D9B7D24934', validatorsRegistry: '0x00000000219ab540356cBB839Cbe05303d7705Fa', securityDeposit: 1000000000n, // 1 gwei - exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours + exitedAssetsClaimDelay: 30 * 60 * 60, // 30 hours // Keeper oracles: [ @@ -135,59 +135,6 @@ export const NETWORKS: { }, } -export const ethValidatorsRegistry = { - abi: [ - { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, - { - anonymous: false, - inputs: [ - { indexed: false, internalType: 'bytes', name: 'pubkey', type: 'bytes' }, - { indexed: false, internalType: 'bytes', name: 'withdrawal_credentials', type: 'bytes' }, - { indexed: false, internalType: 'bytes', name: 'amount', type: 'bytes' }, - { indexed: false, internalType: 'bytes', name: 'signature', type: 'bytes' }, - { indexed: false, internalType: 'bytes', name: 'index', type: 'bytes' }, - ], - name: 'DepositEvent', - type: 'event', - }, - { - inputs: [ - { internalType: 'bytes', name: 'pubkey', type: 'bytes' }, - { internalType: 'bytes', name: 'withdrawal_credentials', type: 'bytes' }, - { internalType: 'bytes', name: 'signature', type: 'bytes' }, - { internalType: 'bytes32', name: 'deposit_data_root', type: 'bytes32' }, - ], - name: 'deposit', - outputs: [], - stateMutability: 'payable', - type: 'function', - }, - { - inputs: [], - name: 'get_deposit_count', - outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'get_deposit_root', - outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }], - name: 'supportsInterface', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'pure', - type: 'function', - }, - ], - bytecode: - '0x608060405234801561001057600080fd5b5060005b601f8110156101025760026021826020811061002c57fe5b01546021836020811061003b57fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106100925780518252601f199092019160209182019101610073565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156100d1573d6000803e3d6000fd5b5050506040513d60208110156100e657600080fd5b5051602160018301602081106100f857fe5b0155600101610014565b506118d680620001136000396000f3fe60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033', -} - export const MAINNET_FORK = { enabled: process.env.ENABLE_MAINNET_FORK === 'true', blockNumber: 19012280, diff --git a/test/EthBlocklistErc20Vault.spec.ts b/test/EthBlocklistErc20Vault.spec.ts new file mode 100644 index 00000000..013aa9df --- /dev/null +++ b/test/EthBlocklistErc20Vault.spec.ts @@ -0,0 +1,320 @@ +import { ethers } from 'hardhat' +import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + EthBlocklistErc20Vault, + Keeper, + OsTokenVaultController, + IKeeperRewards, +} from '../typechain-types' +import { createDepositorMock, ethVaultFixture } from './shared/fixtures' +import { expect } from './shared/expect' +import { ZERO_ADDRESS } from './shared/constants' +import snapshotGasCost from './shared/snapshotGasCost' +import { + collateralizeEthVault, + getHarvestParams, + getRewardsRootProof, + updateRewards, +} from './shared/rewards' +import keccak256 from 'keccak256' +import { extractDepositShares } from './shared/utils' + +describe('EthBlocklistErc20Vault', () => { + const name = 'EthBlocklistVault' + const symbol = 'eBLV' + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Signer, other: Wallet, blocklistManager: Wallet + let vault: EthBlocklistErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController + + beforeEach('deploy fixtures', async () => { + ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() + const fixture = await loadFixture(ethVaultFixture) + vault = await fixture.createEthBlocklistErc20Vault(admin, { + name, + symbol, + capacity, + feePercent, + metadataIpfsHash, + }) + admin = await ethers.getImpersonatedSigner(await vault.admin()) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('EthBlocklistErc20Vault').toString('hex')}`) + }) + + it('has version', async () => { + expect(await vault.version()).to.eq(2) + }) + + it('cannot initialize twice', async () => { + await expect(vault.connect(other).initialize('0x')).revertedWithCustomError( + vault, + 'InvalidInitialization' + ) + }) + + describe('transfer', () => { + const amount = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).setBlocklistManager(blocklistManager.address) + await vault.connect(sender).deposit(sender.address, referrer, { value: amount }) + }) + + it('cannot transfer to blocked user', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault.connect(sender).transfer(other.address, amount) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot transfer from blocked user', async () => { + await vault.connect(other).deposit(other.address, referrer, { value: amount }) + await vault.connect(blocklistManager).updateBlocklist(sender.address, true) + await expect( + vault.connect(other).transfer(sender.address, amount) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can transfer', async () => { + const receipt = await vault.connect(sender).transfer(other.address, amount) + expect(await vault.balanceOf(sender.address)).to.eq(0) + expect(await vault.balanceOf(other.address)).to.eq(amount) + + await expect(receipt) + .to.emit(vault, 'Transfer') + .withArgs(sender.address, other.address, amount) + await snapshotGasCost(receipt) + }) + }) + + describe('deposit', () => { + const assets = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).setBlocklistManager(blocklistManager.address) + }) + + it('cannot be called by blocked sender', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault.connect(other).deposit(other.address, referrer, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot update state and call by blocked sender', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) + const tree = await updateRewards(keeper, [vaultReward]) + + const harvestParams: IKeeperRewards.HarvestParamsStruct = { + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + } + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault + .connect(other) + .updateStateAndDeposit(other.address, referrer, harvestParams, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to blocked user', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault.connect(sender).deposit(other.address, referrer, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by not blocked user', async () => { + const receipt = await vault + .connect(sender) + .deposit(sender.address, referrer, { value: assets }) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, sender.address, assets, shares, referrer) + await snapshotGasCost(receipt) + }) + + it('deposit through receive fallback cannot be called by blocked sender', async () => { + const depositorMock = await createDepositorMock(vault) + const amount = ethers.parseEther('100') + const expectedShares = await vault.convertToShares(amount) + expect(await vault.convertToShares(amount)).to.eq(expectedShares) + await vault.connect(blocklistManager).updateBlocklist(await depositorMock.getAddress(), true) + await expect( + depositorMock.connect(sender).depositToVault({ value: amount }) + ).to.revertedWithCustomError(depositorMock, 'DepositFailed') + }) + + it('deposit through receive fallback can be called by not blocked sender', async () => { + const depositorMock = await createDepositorMock(vault) + const depositorMockAddress = await depositorMock.getAddress() + + const amount = ethers.parseEther('100') + const expectedShares = await vault.convertToShares(amount) + expect(await vault.convertToShares(amount)).to.eq(expectedShares) + const receipt = await depositorMock.connect(sender).depositToVault({ value: amount }) + expect(await vault.getShares(depositorMockAddress)).to.eq(expectedShares) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(depositorMockAddress, depositorMockAddress, amount, expectedShares, ZERO_ADDRESS) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) + osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + }) + + it('cannot mint from blocked user', async () => { + await vault.connect(admin).updateBlocklist(sender.address, true) + await expect( + vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can mint from not blocked user', async () => { + const tx = await vault + .connect(sender) + .mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + await expect(tx).to.emit(vault, 'OsTokenMinted') + await snapshotGasCost(tx) + }) + }) + + describe('ejecting user', () => { + const senderAssets = parseEther('1') + + beforeEach(async () => { + await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) + await vault.connect(admin).setBlocklistManager(blocklistManager.address) + }) + + it('fails for not blocklister', async () => { + await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'AccessDenied' + ) + }) + + it('fails when not harvested', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1.2'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await expect( + vault.connect(blocklistManager).ejectUser(sender.address) + ).to.revertedWithCustomError(vault, 'NotHarvested') + }) + + it('does not fail for user with no vault shares', async () => { + expect(await vault.getShares(other.address)).to.eq(0) + + const tx = await vault.connect(blocklistManager).ejectUser(other.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, other.address, true) + expect(await vault.blockedAccounts(other.address)).to.eq(true) + await snapshotGasCost(tx) + }) + + it('does not fail for user with no osToken shares', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.getShares(sender.address)).to.eq(senderAssets) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + + it('blocklist manager can eject some of the user assets', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const osTokenShares = senderAssets / 2n + const senderShares = await vault.getShares(sender.address) + await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + + expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(senderShares) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + const ejectedShares = senderShares - (await vault.getShares(sender.address)) + expect(ejectedShares).to.be.lessThan(senderShares) + + const ejectedAssets = await vault.convertToAssets(ejectedShares) + expect(ejectedAssets).to.be.lessThan(senderAssets) + + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) + await snapshotGasCost(tx) + }) + + it('blocklist manager can eject all of the user assets', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + }) +}) diff --git a/test/EthBlocklistVault.spec.ts b/test/EthBlocklistVault.spec.ts new file mode 100644 index 00000000..04470156 --- /dev/null +++ b/test/EthBlocklistVault.spec.ts @@ -0,0 +1,281 @@ +import { ethers } from 'hardhat' +import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + EthBlocklistVault, + Keeper, + OsTokenVaultController, + IKeeperRewards, +} from '../typechain-types' +import { createDepositorMock, ethVaultFixture } from './shared/fixtures' +import { expect } from './shared/expect' +import { ZERO_ADDRESS } from './shared/constants' +import snapshotGasCost from './shared/snapshotGasCost' +import { + collateralizeEthVault, + getHarvestParams, + getRewardsRootProof, + updateRewards, +} from './shared/rewards' +import keccak256 from 'keccak256' +import { extractDepositShares } from './shared/utils' + +describe('EthBlocklistVault', () => { + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Signer, other: Wallet, blocklistManager: Wallet + let vault: EthBlocklistVault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController + + beforeEach('deploy fixtures', async () => { + ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() + const fixture = await loadFixture(ethVaultFixture) + vault = await fixture.createEthBlocklistVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + admin = await ethers.getImpersonatedSigner(await vault.admin()) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('EthBlocklistVault').toString('hex')}`) + }) + + it('has version', async () => { + expect(await vault.version()).to.eq(2) + }) + + it('cannot initialize twice', async () => { + await expect(vault.connect(other).initialize('0x')).revertedWithCustomError( + vault, + 'InvalidInitialization' + ) + }) + + describe('deposit', () => { + const assets = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).setBlocklistManager(blocklistManager.address) + }) + + it('cannot be called by blocked sender', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault.connect(other).deposit(other.address, referrer, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot update state and call by blocked sender', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) + const tree = await updateRewards(keeper, [vaultReward]) + + const harvestParams: IKeeperRewards.HarvestParamsStruct = { + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + } + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault + .connect(other) + .updateStateAndDeposit(other.address, referrer, harvestParams, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to blocked user', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + vault.connect(sender).deposit(other.address, referrer, { value: assets }) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by not blocked user', async () => { + const receipt = await vault + .connect(sender) + .deposit(sender.address, referrer, { value: assets }) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, sender.address, assets, shares, referrer) + await snapshotGasCost(receipt) + }) + + it('deposit through receive fallback cannot be called by blocked sender', async () => { + const depositorMock = await createDepositorMock(vault) + const amount = ethers.parseEther('100') + const expectedShares = await vault.convertToShares(amount) + expect(await vault.convertToShares(amount)).to.eq(expectedShares) + await vault.connect(blocklistManager).updateBlocklist(await depositorMock.getAddress(), true) + await expect( + depositorMock.connect(sender).depositToVault({ value: amount }) + ).to.revertedWithCustomError(depositorMock, 'DepositFailed') + }) + + it('deposit through receive fallback can be called by not blocked sender', async () => { + const depositorMock = await createDepositorMock(vault) + const depositorMockAddress = await depositorMock.getAddress() + + const amount = ethers.parseEther('100') + const expectedShares = await vault.convertToShares(amount) + expect(await vault.convertToShares(amount)).to.eq(expectedShares) + const receipt = await depositorMock.connect(sender).depositToVault({ value: amount }) + expect(await vault.getShares(depositorMockAddress)).to.eq(expectedShares) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(depositorMockAddress, depositorMockAddress, amount, expectedShares, ZERO_ADDRESS) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) + osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + }) + + it('cannot mint from blocked user', async () => { + await vault.connect(admin).updateBlocklist(sender.address, true) + await expect( + vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can mint from not blocked user', async () => { + const tx = await vault + .connect(sender) + .mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + await expect(tx).to.emit(vault, 'OsTokenMinted') + await snapshotGasCost(tx) + }) + }) + + describe('ejecting user', () => { + const senderAssets = parseEther('1') + + beforeEach(async () => { + await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) + await vault.connect(admin).setBlocklistManager(blocklistManager.address) + }) + + it('fails for not blocklister', async () => { + await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'AccessDenied' + ) + }) + + it('fails when not harvested', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1.2'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await expect( + vault.connect(blocklistManager).ejectUser(sender.address) + ).to.revertedWithCustomError(vault, 'NotHarvested') + }) + + it('does not fail for user with no vault shares', async () => { + expect(await vault.getShares(other.address)).to.eq(0) + + const tx = await vault.connect(blocklistManager).ejectUser(other.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, other.address, true) + expect(await vault.blockedAccounts(other.address)).to.eq(true) + await snapshotGasCost(tx) + }) + + it('does not fail for user with no osToken shares', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.getShares(sender.address)).to.eq(senderAssets) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + + it('blocklist manager can eject some of the user assets', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const osTokenShares = senderAssets / 2n + const senderShares = await vault.getShares(sender.address) + await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + + expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(senderShares) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + const ejectedShares = senderShares - (await vault.getShares(sender.address)) + expect(ejectedShares).to.be.lessThan(senderShares) + + const ejectedAssets = await vault.convertToAssets(ejectedShares) + expect(ejectedAssets).to.be.lessThan(senderAssets) + + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) + await snapshotGasCost(tx) + }) + + it('blocklist manager can eject all of the user assets', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.blockedAccounts(sender.address)).to.eq(false) + + const tx = await vault.connect(blocklistManager).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'BlocklistUpdated') + .withArgs(blocklistManager.address, sender.address, true) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.blockedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + }) +}) diff --git a/test/EthErc20Vault.spec.ts b/test/EthErc20Vault.spec.ts index 9984a6d4..5526bd3d 100644 --- a/test/EthErc20Vault.spec.ts +++ b/test/EthErc20Vault.spec.ts @@ -1,11 +1,23 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthErc20Vault, Keeper, OsTokenVaultController } from '../typechain-types' +import { + EthErc20Vault, + Keeper, + OsTokenVaultController, + VaultsRegistry, + OsTokenConfig, + SharedMevEscrow, +} from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' -import { createDepositorMock, ethVaultFixture } from './shared/fixtures' +import { + createDepositorMock, + deployEthVaultV1, + encodeEthErc20VaultInitParams, + ethVaultFixture, +} from './shared/fixtures' import { expect } from './shared/expect' -import { SECURITY_DEPOSIT, ZERO_ADDRESS } from './shared/constants' +import { ZERO_ADDRESS } from './shared/constants' import { collateralizeEthVault, getHarvestParams, @@ -15,8 +27,8 @@ import { import keccak256 from 'keccak256' import { extractExitPositionTicket, setBalance } from './shared/utils' import { MAINNET_FORK } from '../helpers/constants' -import { ThenArg } from '../helpers/types' import { registerEthValidator } from './shared/validators' +import { getEthErc20VaultV1Factory } from './shared/contracts' describe('EthErc20Vault', () => { const capacity = ethers.parseEther('1000') @@ -29,9 +41,10 @@ describe('EthErc20Vault', () => { let vault: EthErc20Vault, keeper: Keeper, validatorsRegistry: Contract, - osTokenVaultController: OsTokenVaultController - - let createErc20Vault: ThenArg>['createEthErc20Vault'] + osTokenVaultController: OsTokenVaultController, + vaultsRegistry: VaultsRegistry, + osTokenConfig: OsTokenConfig, + sharedMevEscrow: SharedMevEscrow beforeEach('deploy fixtures', async () => { ;[sender, receiver, admin] = (await (ethers as any).getSigners()).slice(1, 4) @@ -47,7 +60,9 @@ describe('EthErc20Vault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController - createErc20Vault = fixture.createEthErc20Vault + osTokenConfig = fixture.osTokenConfig + vaultsRegistry = fixture.vaultsRegistry + sharedMevEscrow = fixture.sharedMevEscrow }) it('has id', async () => { @@ -55,7 +70,7 @@ describe('EthErc20Vault', () => { }) it('has version', async () => { - expect(await vault.version()).to.eq(1) + expect(await vault.version()).to.eq(2) }) it('deposit emits transfer event', async () => { @@ -102,48 +117,16 @@ describe('EthErc20Vault', () => { await snapshotGasCost(receipt) }) - it('redeem emits transfer event', async () => { - const vault = await createErc20Vault( - admin, - { - capacity, - name, - symbol, - feePercent, - metadataIpfsHash, - }, - false, - true - ) - const amount = ethers.parseEther('100') - await vault.connect(sender).deposit(sender.address, referrer, { value: amount }) - const receiverBalanceBefore = await ethers.provider.getBalance(receiver.address) - const receipt = await vault.connect(sender).redeem(amount, receiver.address) - await expect(receipt) - .to.emit(vault, 'Redeemed') - .withArgs(sender.address, receiver.address, amount, amount) - await expect(receipt).to.emit(vault, 'Transfer').withArgs(sender.address, ZERO_ADDRESS, amount) - - expect(await vault.totalAssets()).to.be.eq(SECURITY_DEPOSIT) - expect(await vault.totalSupply()).to.be.eq(SECURITY_DEPOSIT) - expect(await vault.balanceOf(sender.address)).to.be.eq(0) - expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(SECURITY_DEPOSIT) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + amount - ) - - await snapshotGasCost(receipt) - }) - it('enter exit queue emits transfer event', async () => { await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const queuedSharesBefore = await vault.queuedShares() + expect(await vault.totalExitingAssets()).to.be.eq(0) + const totalExitingBefore = await vault.totalExitingAssets() const totalAssetsBefore = await vault.totalAssets() const totalSharesBefore = await vault.totalShares() - const assets = ethers.parseEther('100') - let shares = await vault.convertToShares(assets) - await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) + const amount = ethers.parseEther('100') + let shares = await vault.convertToShares(amount) + await vault.connect(sender).deposit(sender.address, referrer, { value: amount }) if (MAINNET_FORK.enabled) { shares += 1n // rounding error } @@ -153,19 +136,34 @@ describe('EthErc20Vault', () => { const positionTicket = await extractExitPositionTicket(receipt) await expect(receipt) .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, receiver.address, positionTicket, shares) - await expect(receipt) - .to.emit(vault, 'Transfer') - .withArgs(sender.address, await vault.getAddress(), shares) - expect(await vault.queuedShares()).to.be.eq(queuedSharesBefore + shares) - expect(await vault.totalAssets()).to.be.eq(totalAssetsBefore + assets) - expect(await vault.totalSupply()).to.be.eq(totalSharesBefore + shares) + .withArgs(sender.address, receiver.address, positionTicket, amount) + await expect(receipt).to.emit(vault, 'Transfer').withArgs(sender.address, ZERO_ADDRESS, shares) + expect(await vault.totalExitingAssets()).to.be.eq(totalExitingBefore + amount) + expect(await vault.totalAssets()).to.be.eq(totalAssetsBefore) + expect(await vault.totalSupply()).to.be.eq(totalSharesBefore) expect(await vault.balanceOf(sender.address)).to.be.eq(0) await snapshotGasCost(receipt) }) it('update exit queue emits transfer event', async () => { + const vault = await deployEthVaultV1( + await getEthErc20VaultV1Factory(), + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthErc20VaultInitParams({ + capacity, + name, + symbol, + feePercent, + metadataIpfsHash, + }) + ) const validatorDeposit = ethers.parseEther('32') await vault .connect(admin) diff --git a/test/EthFoxVault.spec.ts b/test/EthFoxVault.spec.ts index b062ba75..3e42e168 100644 --- a/test/EthFoxVault.spec.ts +++ b/test/EthFoxVault.spec.ts @@ -56,7 +56,7 @@ describe('EthFoxVault', () => { }) it('has version', async () => { - expect(await vault.version()).to.eq(1) + expect(await vault.version()).to.eq(2) }) describe('set blocklist manager', () => { @@ -216,21 +216,6 @@ describe('EthFoxVault', () => { .withArgs(blocklistManager.address, other.address, true) expect(await vault.blockedAccounts(other.address)).to.eq(true) await expect(tx).to.not.emit(vault, 'ExitQueueEntered') - await expect(tx).to.not.emit(vault, 'Redeemed') - await snapshotGasCost(tx) - }) - - it('blocklist manager can eject all of the user assets for not collateralized vault', async () => { - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - await expect(tx) - .to.emit(vault, 'Redeemed') - .withArgs(sender.address, sender.address, senderAssets, senderShares) - await expect(tx).to.emit(vault, 'UserEjected').withArgs(sender.address, senderShares) - expect(await vault.getShares(sender.address)).to.eq(0) await snapshotGasCost(tx) }) diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 35141148..08cb4340 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -84,7 +84,7 @@ describe('EthGenesisVault', () => { const adminAddr = await admin.getAddress() // VaultVersion - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) expect(await vault.vaultId()).to.be.eq(`0x${keccak256('EthGenesisVault').toString('hex')}`) // VaultFee @@ -96,23 +96,7 @@ describe('EthGenesisVault', () => { }) it('has version', async () => { - expect(await vault.version()).to.eq(1) - }) - - it('applies ownership transfer', async () => { - await acceptPoolEscrowOwnership() - expect(await poolEscrow.owner()).to.eq(await vault.getAddress()) - }) - - it('apply ownership cannot be called second time', async () => { - await acceptPoolEscrowOwnership() - await expect(vault.connect(other).acceptPoolEscrowOwnership()).to.be.revertedWithCustomError( - vault, - 'AccessDenied' - ) - await expect(vault.connect(admin).acceptPoolEscrowOwnership()).to.be.revertedWith( - 'PoolEscrow: caller is not the future owner' - ) + expect(await vault.version()).to.eq(2) }) describe('migrate', () => { @@ -235,7 +219,7 @@ describe('EthGenesisVault', () => { await acceptPoolEscrowOwnership() await collatEthVault() - let assets = ethers.parseEther('10') + const assets = ethers.parseEther('10') let tx = await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: assets }) const shares = await extractDepositShares(tx) @@ -264,52 +248,16 @@ describe('EthGenesisVault', () => { unlockedMevReward: harvestParams.unlockedMevReward, }) const exitQueueIndex = await vault.getExitQueueIndex(positionTicket) - if (MAINNET_FORK.enabled) { - assets -= 1n - } tx = await vault.connect(other).claimExitedAssets(positionTicket, timestamp, exitQueueIndex) await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, poolEscrowBalance + vaultBalance) - await expect(tx) - .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(other.address, positionTicket, 0, assets) + await expect(tx).to.emit(vault, 'ExitedAssetsClaimed').withArgs(other.address, 0, assets) expect(await ethers.provider.getBalance(await poolEscrow.getAddress())).to.eq(0) await snapshotGasCost(tx) }) - it('pulls assets on redeem', async () => { - const [vault, , poolEscrow] = await createGenesisVault( - admin, - { - capacity, - feePercent, - metadataIpfsHash, - }, - true - ) - await vault.connect(admin).acceptPoolEscrowOwnership() - const assets = ethers.parseEther('10') - let tx = await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: assets }) - const shares = await extractDepositShares(tx) - - await setBalance(await vault.getAddress(), 0n) - await setBalance(await poolEscrow.getAddress(), assets) - - expect(await vault.withdrawableAssets()).to.eq(assets) - - tx = await vault.connect(other).redeem(shares, other.address) - await expect(tx) - .to.emit(vault, 'Redeemed') - .withArgs(other.address, other.address, shares, shares) - await expect(tx).to.not.emit(vault, 'Deposited') - await expect(tx) - .to.emit(poolEscrow, 'Withdrawn') - .withArgs(await vault.getAddress(), await vault.getAddress(), assets) - expect(await ethers.provider.getBalance(await poolEscrow.getAddress())).to.eq(0) - }) - it('pulls assets on single validator registration', async () => { await acceptPoolEscrowOwnership() await collatEthVault() diff --git a/test/EthPrivErc20Vault.spec.ts b/test/EthPrivErc20Vault.spec.ts index 19b20480..6d6af7ec 100644 --- a/test/EthPrivErc20Vault.spec.ts +++ b/test/EthPrivErc20Vault.spec.ts @@ -1,5 +1,5 @@ import { ethers } from 'hardhat' -import { Contract, Signer, Wallet } from 'ethers' +import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthPrivErc20Vault, IKeeperRewards, Keeper } from '../typechain-types' import { ThenArg } from '../helpers/types' @@ -17,13 +17,13 @@ describe('EthPrivErc20Vault', () => { const feePercent = 1000 const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' - let sender: Wallet, admin: Signer, other: Wallet + let sender: Wallet, admin: Signer, other: Wallet, whitelister: Wallet let vault: EthPrivErc20Vault, keeper: Keeper, validatorsRegistry: Contract let createPrivateVault: ThenArg>['createEthPrivErc20Vault'] beforeEach('deploy fixtures', async () => { - ;[sender, admin, other] = await (ethers as any).getSigners() + ;[sender, admin, other, whitelister] = await (ethers as any).getSigners() ;({ createEthPrivErc20Vault: createPrivateVault, keeper, @@ -44,13 +44,14 @@ describe('EthPrivErc20Vault', () => { }) it('has version', async () => { - expect(await vault.version()).to.eq(1) + expect(await vault.version()).to.eq(2) }) describe('deposit', () => { const amount = ethers.parseEther('1') beforeEach(async () => { + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) await vault.connect(admin).updateWhitelist(sender.address, true) }) @@ -134,4 +135,159 @@ describe('EthPrivErc20Vault', () => { await snapshotGasCost(receipt) }) }) + + describe('transfer', () => { + const amount = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(sender.address, true) + await vault.connect(sender).deposit(sender.address, referrer, { value: amount }) + }) + + it('cannot transfer to not whitelisted user', async () => { + await expect( + vault.connect(sender).transfer(other.address, amount) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot transfer from not whitelisted user', async () => { + await vault.connect(admin).updateWhitelist(other.address, true) + await vault.connect(sender).transfer(other.address, amount) + await vault.connect(admin).updateWhitelist(sender.address, false) + await expect( + vault.connect(other).transfer(sender.address, amount) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can transfer to whitelisted user', async () => { + await vault.connect(admin).updateWhitelist(other.address, true) + const receipt = await vault.connect(sender).transfer(other.address, amount) + expect(await vault.balanceOf(sender.address)).to.eq(0) + expect(await vault.balanceOf(other.address)).to.eq(amount) + + await expect(receipt) + .to.emit(vault, 'Transfer') + .withArgs(sender.address, other.address, amount) + await snapshotGasCost(receipt) + }) + }) + + describe('ejecting user', () => { + const senderAssets = parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(sender.address, true) + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) + await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) + await vault.connect(admin).setWhitelister(whitelister.address) + }) + + it('fails for not whitelister', async () => { + await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'AccessDenied' + ) + }) + + it('fails when not harvested', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1.2'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await expect(vault.connect(whitelister).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'NotHarvested' + ) + }) + + it('does not fail for user with no vault shares', async () => { + await vault.connect(whitelister).updateWhitelist(other.address, true) + + expect(await vault.getShares(other.address)).to.eq(0) + expect(await vault.whitelistedAccounts(other.address)).to.eq(true) + + const tx = await vault.connect(whitelister).ejectUser(other.address) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, other.address, false) + expect(await vault.whitelistedAccounts(other.address)).to.eq(false) + await snapshotGasCost(tx) + }) + + it('does not fail for user with no osToken shares', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderAssets) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + + it('whitelister can eject some of the user assets', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const osTokenShares = senderAssets / 2n + const senderShares = await vault.getShares(sender.address) + await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + + expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderShares) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + const ejectedShares = senderShares - (await vault.getShares(sender.address)) + expect(ejectedShares).to.be.lessThan(senderShares) + + const ejectedAssets = await vault.convertToAssets(ejectedShares) + expect(ejectedAssets).to.be.lessThan(senderAssets) + + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) + await snapshotGasCost(tx) + }) + + it('whitelister can eject all of the user assets', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, 0n, senderAssets) + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + }) }) diff --git a/test/EthPrivVault.spec.ts b/test/EthPrivVault.spec.ts new file mode 100644 index 00000000..605b78d2 --- /dev/null +++ b/test/EthPrivVault.spec.ts @@ -0,0 +1,202 @@ +import { ethers } from 'hardhat' +import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { EthPrivVault, Keeper, OsTokenVaultController } from '../typechain-types' +import { ethVaultFixture } from './shared/fixtures' +import { expect } from './shared/expect' +import { ZERO_ADDRESS } from './shared/constants' +import snapshotGasCost from './shared/snapshotGasCost' +import { collateralizeEthVault, updateRewards } from './shared/rewards' +import keccak256 from 'keccak256' +import { extractDepositShares, extractExitPositionTicket } from './shared/utils' + +describe('EthPrivVault', () => { + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Signer, other: Wallet, whitelister: Wallet + let vault: EthPrivVault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController + + beforeEach('deploy fixtures', async () => { + ;[sender, admin, other, whitelister] = await (ethers as any).getSigners() + const fixture = await loadFixture(ethVaultFixture) + vault = await fixture.createEthPrivVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + admin = await ethers.getImpersonatedSigner(await vault.admin()) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('EthPrivVault').toString('hex')}`) + }) + + it('has version', async () => { + expect(await vault.version()).to.eq(2) + }) + + it('cannot initialize twice', async () => { + await expect(vault.connect(other).initialize('0x')).revertedWithCustomError( + vault, + 'InvalidInitialization' + ) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(admin).updateWhitelist(sender.address, true) + await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) + osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + }) + + it('cannot mint from not whitelisted user', async () => { + await vault.connect(admin).updateWhitelist(sender.address, false) + await expect( + vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can mint from not whitelisted user', async () => { + const tx = await vault + .connect(sender) + .mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + await expect(tx).to.emit(vault, 'OsTokenMinted') + await snapshotGasCost(tx) + }) + }) + + describe('ejecting user', () => { + const senderAssets = parseEther('1') + let senderShares: bigint + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(sender.address, true) + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) + await vault.connect(admin).setWhitelister(whitelister.address) + const tx = await vault + .connect(sender) + .deposit(sender.address, referrer, { value: senderAssets }) + senderShares = await extractDepositShares(tx) + }) + + it('fails for not whitelister', async () => { + await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'AccessDenied' + ) + }) + + it('fails when not harvested', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await updateRewards(keeper, [ + { + vault: await vault.getAddress(), + reward: ethers.parseEther('1.2'), + unlockedMevReward: ethers.parseEther('0'), + }, + ]) + await expect(vault.connect(whitelister).ejectUser(sender.address)).to.revertedWithCustomError( + vault, + 'NotHarvested' + ) + }) + + it('does not fail for user with no vault shares', async () => { + await vault.connect(whitelister).updateWhitelist(other.address, true) + + expect(await vault.getShares(other.address)).to.eq(0) + expect(await vault.whitelistedAccounts(other.address)).to.eq(true) + + const tx = await vault.connect(whitelister).ejectUser(other.address) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, other.address, false) + expect(await vault.whitelistedAccounts(other.address)).to.eq(false) + await snapshotGasCost(tx) + }) + + it('does not fail for user with no osToken shares', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderShares) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + const positionTicket = await extractExitPositionTicket(tx) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, positionTicket, senderAssets) + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + + it('whitelister can eject some of the user assets', async () => { + await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + const osTokenShares = senderAssets / 2n + await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + + expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + expect(await vault.getShares(sender.address)).to.eq(senderShares) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + const ejectedShares = senderShares - (await vault.getShares(sender.address)) + expect(ejectedShares).to.be.lessThan(senderShares) + + const ejectedAssets = await vault.convertToAssets(ejectedShares) + expect(ejectedAssets).to.be.lessThan(senderAssets) + + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx).to.emit(vault, 'ExitQueueEntered') + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) + await snapshotGasCost(tx) + }) + + it('whitelister can eject all of the user assets', async () => { + expect(await vault.osTokenPositions(sender.address)).to.eq(0) + expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) + + const tx = await vault.connect(whitelister).ejectUser(sender.address) + const positionTicket = await extractExitPositionTicket(tx) + await expect(tx) + .to.emit(vault, 'WhitelistUpdated') + .withArgs(whitelister.address, sender.address, false) + await expect(tx) + .to.emit(vault, 'ExitQueueEntered') + .withArgs(sender.address, sender.address, positionTicket, senderAssets) + + expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) + expect(await vault.getShares(sender.address)).to.eq(0) + await snapshotGasCost(tx) + }) + }) +}) diff --git a/test/EthVault.deposit.spec.ts b/test/EthVault.deposit.spec.ts index 4ca0123e..de7e52f3 100644 --- a/test/EthVault.deposit.spec.ts +++ b/test/EthVault.deposit.spec.ts @@ -182,7 +182,6 @@ describe('EthVault - deposit', () => { await expect(receipt).to.emit(vault, 'Deposited') await expect(receipt).to.emit(keeper, 'Harvested') await expect(receipt).to.emit(mevEscrow, 'Harvested') - await expect(receipt).to.emit(vault, 'CheckpointCreated') await snapshotGasCost(receipt) }) diff --git a/test/EthVault.multicall.spec.ts b/test/EthVault.multicall.spec.ts index 3575b35c..ea7d445e 100644 --- a/test/EthVault.multicall.spec.ts +++ b/test/EthVault.multicall.spec.ts @@ -144,7 +144,7 @@ describe('EthVault - multicall', () => { receipt = await vault.connect(sender).multicall(calls) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(sender.address, queueTicket, 0, userAssets - 1n) // 1 wei is left in the vault + .withArgs(sender.address, 0, userAssets - 1n) // 1 wei is left in the vault await snapshotGasCost(receipt) }) diff --git a/test/EthVault.register.spec.ts b/test/EthVault.register.spec.ts index 9c752f2c..5ec5684b 100644 --- a/test/EthVault.register.spec.ts +++ b/test/EthVault.register.spec.ts @@ -178,7 +178,7 @@ describe('EthVault - register', () => { indexes = validators.map((v) => sortedVals.indexOf(v)) const balance = validatorDeposit * BigInt(validators.length) + - (await vault.convertToAssets(await vault.queuedShares())) + + (await vault.totalExitingAssets()) + (await ethers.provider.getBalance(vaultAddr)) await setBalance(vaultAddr, balance) signatures = getOraclesSignatures( diff --git a/test/EthVault.state.spec.ts b/test/EthVault.state.spec.ts index 5b2c69b0..a71881cc 100644 --- a/test/EthVault.state.spec.ts +++ b/test/EthVault.state.spec.ts @@ -1,10 +1,18 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, Keeper, OwnMevEscrow__factory, SharedMevEscrow } from '../typechain-types' +import { + EthVault, + Keeper, + OwnMevEscrow__factory, + SharedMevEscrow, + VaultsRegistry, + OsTokenVaultController, + OsTokenConfig, +} from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' -import { ethVaultFixture } from './shared/fixtures' +import { deployEthVaultV1, encodeEthVaultInitParams, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' import { MAX_UINT256, @@ -15,11 +23,13 @@ import { } from './shared/constants' import { extractDepositShares, setBalance } from './shared/utils' import { + collateralizeEthV1Vault, collateralizeEthVault, getHarvestParams, getRewardsRootProof, updateRewards, } from './shared/rewards' +import { getEthVaultV1Factory } from './shared/contracts' describe('EthVault - state', () => { const holderAssets = ethers.parseEther('1') @@ -31,7 +41,10 @@ describe('EthVault - state', () => { let vault: EthVault, keeper: Keeper, sharedMevEscrow: SharedMevEscrow, - validatorsRegistry: Contract + validatorsRegistry: Contract, + vaultsRegistry: VaultsRegistry, + osTokenVaultController: OsTokenVaultController, + osTokenConfig: OsTokenConfig let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] @@ -44,6 +57,9 @@ describe('EthVault - state', () => { keeper, validatorsRegistry, sharedMevEscrow, + vaultsRegistry, + osTokenVaultController, + osTokenConfig, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, { capacity, @@ -209,6 +225,60 @@ describe('EthVault - state', () => { await snapshotGasCost(receipt) }) + it('splits penalty between exiting assets and staking assets', async () => { + await expect(await vault.totalExitingAssets()).to.be.eq(0) + const holder = other + let totalShares = await vault.totalShares() + let totalAssets = await vault.totalAssets() + const withdrawableAssets = await vault.withdrawableAssets() + const vaultBalance = await ethers.provider.getBalance(await vault.getAddress()) + const unclaimedAssets = vaultBalance - withdrawableAssets + + const holderAssets = totalAssets + const tx = await vault.deposit(holder.address, ZERO_ADDRESS, { + value: holderAssets, + }) + const holderShares = await extractDepositShares(tx) + expect(holderShares).to.be.eq(totalShares) + expect(await vault.getShares(holder.address)).to.be.eq(holderShares) + totalShares *= 2n + totalAssets *= 2n + + expect(await vault.totalShares()).to.eq(totalShares) + expect(await vault.totalAssets()).to.eq(totalAssets) + + await vault.connect(holder).enterExitQueue(holderShares, holder.address) + const exitingAssets = await vault.totalExitingAssets() + expect(exitingAssets).to.eq(holderAssets) + expect(await vault.totalShares()).to.be.eq(totalShares / 2n) + expect(await vault.getShares(holder.address)).to.be.eq(0) + + // all assets are slashed + await setBalance(await vault.getAddress(), unclaimedAssets) + const vaultReward = getHarvestParams(await vault.getAddress(), -totalAssets, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(tree, { + vault: vaultReward.vault, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + }) + + const receipt = await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + await expect(receipt) + .emit(keeper, 'Harvested') + .withArgs(await vault.getAddress(), tree.root, -totalAssets, 0n) + await expect(receipt).not.emit(vault, 'FeeSharesMinted') + expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(unclaimedAssets) + expect(await vault.totalAssets()).to.be.eq(0n) + expect(await vault.totalExitingAssets()).to.be.eq(0n) + await snapshotGasCost(receipt) + }) + it('allocates fee to recipient when delta is above zero', async () => { // create vault with own mev escrow const vault = await createVault( @@ -264,17 +334,22 @@ describe('EthVault - state', () => { }) it('updates exit queue', async () => { - const vault = await createVault( + const vault = await deployEthVaultV1( + await getEthVaultV1Factory(), admin, - { + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthVaultInitParams({ capacity, feePercent, metadataIpfsHash, - }, - false, - true + }) ) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthV1Vault(vault, keeper, validatorsRegistry, admin) const tx = await vault .connect(holder) .deposit(holder.address, ZERO_ADDRESS, { value: holderAssets }) diff --git a/test/EthVault.upgrade.spec.ts b/test/EthVault.upgrade.spec.ts index 7b0b0c0a..b65b6ac1 100644 --- a/test/EthVault.upgrade.spec.ts +++ b/test/EthVault.upgrade.spec.ts @@ -1,32 +1,80 @@ import { ethers } from 'hardhat' -import { Signer, Wallet } from 'ethers' +import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthVault, + EthVaultFactory, EthVaultV3Mock, + EthVaultV3Mock__factory, + Keeper, + OsTokenConfig, + OsTokenVaultController, + SharedMevEscrow, VaultsRegistry, - EthVaultV2Mock__factory, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' -import { deployVaultImplementation, ethVaultFixture } from './shared/fixtures' +import { + deployEthVaultV1, + deployVaultImplementation, + encodeEthErc20VaultInitParams, + encodeEthVaultInitParams, + ethVaultFixture, +} from './shared/fixtures' import { expect } from './shared/expect' -import { EXITING_ASSETS_MIN_DELAY, MAX_UINT256, ZERO_ADDRESS } from './shared/constants' +import { + EXITING_ASSETS_MIN_DELAY, + MAX_UINT256, + SECURITY_DEPOSIT, + ZERO_ADDRESS, +} from './shared/constants' +import { collateralizeEthV1Vault } from './shared/rewards' +import { + getEthErc20VaultV1Factory, + getEthGenesisVaultV1Factory, + getEthPrivErc20VaultV1Factory, + getEthPrivVaultV1Factory, + getEthVaultV1Factory, +} from './shared/contracts' +import { ThenArg } from '../helpers/types' describe('EthVault - upgrade', () => { const capacity = ethers.parseEther('1000') const feePercent = 1000 const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7r' let admin: Signer, dao: Wallet, other: Wallet - let vault: EthVault, vaultsRegistry: VaultsRegistry, updatedVault: EthVaultV3Mock + let vault: EthVault, + vaultsRegistry: VaultsRegistry, + keeper: Keeper, + validatorsRegistry: Contract, + updatedVault: EthVaultV3Mock, + sharedMevEscrow: SharedMevEscrow, + osTokenConfig: OsTokenConfig, + osTokenVaultController: OsTokenVaultController, + ethVaultFactory: EthVaultFactory, + ethPrivVaultFactory: EthVaultFactory, + ethErc20VaultFactory: EthVaultFactory, + ethPrivErc20VaultFactory: EthVaultFactory let currImpl: string - let newImpl: string + let mockImpl: string let callData: string let fixture: any + let createGenesisVault: ThenArg>['createEthGenesisVault'] + beforeEach('deploy fixture', async () => { ;[dao, admin, other] = await (ethers as any).getSigners() fixture = await loadFixture(ethVaultFixture) vaultsRegistry = fixture.vaultsRegistry + validatorsRegistry = fixture.validatorsRegistry + keeper = fixture.keeper + sharedMevEscrow = fixture.sharedMevEscrow + osTokenConfig = fixture.osTokenConfig + osTokenVaultController = fixture.osTokenVaultController + ethVaultFactory = fixture.ethVaultFactory + ethPrivVaultFactory = fixture.ethPrivVaultFactory + ethErc20VaultFactory = fixture.ethErc20VaultFactory + ethPrivErc20VaultFactory = fixture.ethPrivErc20VaultFactory + createGenesisVault = fixture.createEthGenesisVault vault = await fixture.createEthVault(admin, { capacity, feePercent, @@ -34,8 +82,8 @@ describe('EthVault - upgrade', () => { }) admin = await ethers.getImpersonatedSigner(await vault.admin()) - newImpl = await deployVaultImplementation( - 'EthVaultV2Mock', + mockImpl = await deployVaultImplementation( + 'EthVaultV3Mock', fixture.keeper, fixture.vaultsRegistry, await fixture.validatorsRegistry.getAddress(), @@ -46,8 +94,8 @@ describe('EthVault - upgrade', () => { ) currImpl = await vault.implementation() callData = ethers.AbiCoder.defaultAbiCoder().encode(['uint128'], [100]) - await vaultsRegistry.connect(dao).addVaultImpl(newImpl) - updatedVault = EthVaultV2Mock__factory.connect( + await vaultsRegistry.connect(dao).addVaultImpl(mockImpl) + updatedVault = EthVaultV3Mock__factory.connect( await vault.getAddress(), await ethers.provider.getSigner() ) @@ -55,36 +103,36 @@ describe('EthVault - upgrade', () => { it('fails from not admin', async () => { await expect( - vault.connect(other).upgradeToAndCall(newImpl, callData) + vault.connect(other).upgradeToAndCall(mockImpl, callData) ).to.revertedWithCustomError(vault, 'AccessDenied') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails with zero new implementation address', async () => { await expect( vault.connect(admin).upgradeToAndCall(ZERO_ADDRESS, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails for the same implementation', async () => { await expect( vault.connect(admin).upgradeToAndCall(currImpl, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails for not approved implementation', async () => { - await vaultsRegistry.connect(dao).removeVaultImpl(newImpl) + await vaultsRegistry.connect(dao).removeVaultImpl(mockImpl) await expect( - vault.connect(admin).upgradeToAndCall(newImpl, callData) + vault.connect(admin).upgradeToAndCall(mockImpl, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails for implementation with different vault id', async () => { const newImpl = await deployVaultImplementation( - 'EthPrivVaultV2Mock', + 'EthPrivVaultV3Mock', fixture.keeper, fixture.vaultsRegistry, await fixture.validatorsRegistry.getAddress(), @@ -98,12 +146,12 @@ describe('EthVault - upgrade', () => { await expect( vault.connect(admin).upgradeToAndCall(newImpl, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails for implementation with too high version', async () => { const newImpl = await deployVaultImplementation( - 'EthVaultV3Mock', + 'EthVaultV4Mock', fixture.keeper, fixture.vaultsRegistry, await fixture.validatorsRegistry.getAddress(), @@ -117,7 +165,7 @@ describe('EthVault - upgrade', () => { await expect( vault.connect(admin).upgradeToAndCall(newImpl, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('fails with invalid call data', async () => { @@ -125,21 +173,37 @@ describe('EthVault - upgrade', () => { vault .connect(admin) .upgradeToAndCall( - newImpl, + mockImpl, ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [MAX_UINT256]) ) ).to.revertedWithCustomError(vault, 'FailedInnerCall') - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) }) it('works with valid call data', async () => { - const receipt = await vault.connect(admin).upgradeToAndCall(newImpl, callData) - expect(await vault.version()).to.be.eq(2) - expect(await vault.implementation()).to.be.eq(newImpl) + const receipt = await vault.connect(admin).upgradeToAndCall(mockImpl, callData) + expect(await vault.version()).to.be.eq(3) + expect(await vault.implementation()).to.be.eq(mockImpl) expect(await updatedVault.newVar()).to.be.eq(100) expect(await updatedVault.somethingNew()).to.be.eq(true) await expect( - vault.connect(admin).upgradeToAndCall(newImpl, callData) + vault.connect(admin).upgradeToAndCall(mockImpl, callData) + ).to.revertedWithCustomError(vault, 'UpgradeFailed') + await expect(updatedVault.connect(admin).initialize(callData)).to.revertedWithCustomError( + updatedVault, + 'InvalidInitialization' + ) + await snapshotGasCost(receipt) + }) + + it('works with valid call data', async () => { + const receipt = await vault.connect(admin).upgradeToAndCall(mockImpl, callData) + expect(await vault.version()).to.be.eq(3) + expect(await vault.implementation()).to.be.eq(mockImpl) + expect(await updatedVault.newVar()).to.be.eq(100) + expect(await updatedVault.somethingNew()).to.be.eq(true) + await expect( + vault.connect(admin).upgradeToAndCall(mockImpl, callData) ).to.revertedWithCustomError(vault, 'UpgradeFailed') await expect(updatedVault.connect(admin).initialize(callData)).to.revertedWithCustomError( updatedVault, @@ -147,4 +211,132 @@ describe('EthVault - upgrade', () => { ) await snapshotGasCost(receipt) }) + + it('does not modify the state variables', async () => { + const vaults: Contract[] = [] + for (const factory of [await getEthVaultV1Factory(), await getEthPrivVaultV1Factory()]) { + const vault = await deployEthVaultV1( + factory, + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthVaultInitParams({ + capacity, + feePercent, + metadataIpfsHash, + }) + ) + vaults.push(vault) + } + for (const factory of [ + await getEthErc20VaultV1Factory(), + await getEthPrivErc20VaultV1Factory(), + ]) { + const vault = await deployEthVaultV1( + factory, + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthErc20VaultInitParams({ + capacity, + feePercent, + metadataIpfsHash, + name: 'Vault', + symbol: 'VLT', + }) + ) + vaults.push(vault) + } + + const checkVault = async (vault: Contract, newImpl: string) => { + await collateralizeEthV1Vault(vault, keeper, validatorsRegistry, admin) + await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: parseEther('3') }) + await vault.connect(other).enterExitQueue(parseEther('1'), other.address) + await vault.connect(other).mintOsToken(other.address, parseEther('1'), ZERO_ADDRESS) + + const userShares = await vault.getShares(other.address) + const userAssets = await vault.convertToAssets(userShares) + const osTokenPosition = await vault.osTokenPositions(other.address) + const keysManager = await vault.keysManager() + const mevEscrow = await vault.mevEscrow() + const totalAssets = await vault.totalAssets() + const totalShares = await vault.totalShares() + const validatorIndex = await vault.validatorIndex() + const validatorsRoot = await vault.validatorsRoot() + expect(await vault.version()).to.be.eq(1) + + const receipt = await vault.connect(admin).upgradeToAndCall(newImpl, '0x') + expect(await vault.version()).to.be.eq(2) + expect(await vault.implementation()).to.be.eq(newImpl) + expect(await vault.getShares(other.address)).to.be.eq(userShares) + expect(await vault.convertToAssets(userShares)).to.be.deep.eq(userAssets) + expect(await vault.osTokenPositions(other.address)).to.be.above(osTokenPosition) + expect(await vault.keysManager()).to.be.eq(keysManager) + expect(await vault.mevEscrow()).to.be.eq(mevEscrow) + expect(await vault.totalAssets()).to.be.eq(totalAssets) + expect(await vault.totalShares()).to.be.eq(totalShares) + expect(await vault.validatorIndex()).to.be.eq(validatorIndex) + expect(await vault.validatorsRoot()).to.be.eq(validatorsRoot) + await snapshotGasCost(receipt) + } + await checkVault(vaults[0], await ethVaultFactory.implementation()) + await checkVault(vaults[2], await ethErc20VaultFactory.implementation()) + + await vaults[1].connect(admin).updateWhitelist(other.address, true) + await checkVault(vaults[1], await ethPrivVaultFactory.implementation()) + + await vaults[3].connect(admin).updateWhitelist(other.address, true) + await checkVault(vaults[3], await ethPrivErc20VaultFactory.implementation()) + + const [v2GenesisVault, rewardEthToken, poolEscrow] = await createGenesisVault( + admin, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + const factory = await getEthGenesisVaultV1Factory() + const constructorArgs = [ + await keeper.getAddress(), + await vaultsRegistry.getAddress(), + await validatorsRegistry.getAddress(), + await osTokenVaultController.getAddress(), + await osTokenConfig.getAddress(), + await sharedMevEscrow.getAddress(), + await poolEscrow.getAddress(), + await rewardEthToken.getAddress(), + EXITING_ASSETS_MIN_DELAY, + ] + const contract = await factory.deploy(...constructorArgs) + const genesisImpl = await contract.getAddress() + const genesisImplV2 = await v2GenesisVault.implementation() + await vaultsRegistry.addVaultImpl(genesisImpl) + + const proxyFactory = await ethers.getContractFactory('ERC1967Proxy') + const proxy = await proxyFactory.deploy(genesisImpl, '0x') + const proxyAddress = await proxy.getAddress() + const genesisVault = new Contract(proxyAddress, contract.interface, admin) + await rewardEthToken.connect(dao).setVault(proxyAddress) + await poolEscrow.connect(dao).commitOwnershipTransfer(proxyAddress) + await genesisVault.initialize( + ethers.AbiCoder.defaultAbiCoder().encode( + ['address', 'tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)'], + [await admin.getAddress(), [capacity, feePercent, metadataIpfsHash]] + ), + { value: SECURITY_DEPOSIT } + ) + await genesisVault.acceptPoolEscrowOwnership() + await vaultsRegistry.addVault(proxyAddress) + await checkVault(genesisVault, genesisImplV2) + }) }) diff --git a/test/EthVault.whitelist.spec.ts b/test/EthVault.whitelist.spec.ts index 80d9c768..9d7ac2be 100644 --- a/test/EthVault.whitelist.spec.ts +++ b/test/EthVault.whitelist.spec.ts @@ -74,9 +74,10 @@ describe('EthVault - whitelist', () => { it('cannot be updated twice', async () => { await vault.connect(whitelister).updateWhitelist(sender.address, true) - await expect( - vault.connect(whitelister).updateWhitelist(sender.address, true) - ).to.revertedWithCustomError(vault, 'WhitelistAlreadyUpdated') + await expect(vault.connect(whitelister).updateWhitelist(sender.address, true)).to.not.emit( + vault, + 'WhitelistUpdated' + ) }) it('can be updated by whitelister', async () => { @@ -102,6 +103,7 @@ describe('EthVault - whitelist', () => { const amount = ethers.parseEther('1') beforeEach(async () => { + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) await vault.connect(admin).updateWhitelist(sender.address, true) }) diff --git a/test/EthVault.withdraw.spec.ts b/test/EthVault.withdraw.spec.ts index 1a7d916e..75f7ba83 100644 --- a/test/EthVault.withdraw.spec.ts +++ b/test/EthVault.withdraw.spec.ts @@ -1,14 +1,27 @@ import { ethers } from 'hardhat' -import { Contract, Signer, Wallet } from 'ethers' +import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, EthVaultMock, IKeeperRewards, Keeper, SharedMevEscrow } from '../typechain-types' +import { + EthVault, + IKeeperRewards, + Keeper, + SharedMevEscrow, + VaultsRegistry, + OsTokenVaultController, + OsTokenConfig, + EthVault__factory, +} from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' -import { ethVaultFixture } from './shared/fixtures' +import { + deployEthVaultV1, + encodeEthVaultInitParams, + ethVaultFixture, + upgradeVaultToV2, +} from './shared/fixtures' import { expect } from './shared/expect' import { EXITING_ASSETS_MIN_DELAY, - MAX_UINT128, ONE_DAY, PANIC_CODES, SECURITY_DEPOSIT, @@ -21,8 +34,13 @@ import { increaseTime, setBalance, } from './shared/utils' -import { collateralizeEthVault, getRewardsRootProof, updateRewards } from './shared/rewards' -import { registerEthValidator } from './shared/validators' +import { + collateralizeEthV1Vault, + getHarvestParams, + getRewardsRootProof, + updateRewards, +} from './shared/rewards' +import { getEthVaultV1Factory } from './shared/contracts' const validatorDeposit = ethers.parseEther('32') @@ -31,135 +49,124 @@ describe('EthVault - withdraw', () => { const feePercent = 1000 const referrer = '0x' + '1'.repeat(40) const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' - const holderAssets = ethers.parseEther('1') - let holderShares: bigint + let positionTicketV1: bigint, positionTicketV2: bigint + let timestampV1: number, timestampV2: number + let holderV1: Wallet, holderV2: Wallet, receiver: Wallet, admin: Signer, other: Wallet + let holderV1Shares: bigint + const holderV1Assets = parseEther('1') + const holderV2Assets = parseEther('2') - let holder: Wallet, receiver: Wallet, admin: Signer, other: Wallet let vault: EthVault, keeper: Keeper, sharedMevEscrow: SharedMevEscrow, + vaultsRegistry: VaultsRegistry, + osTokenVaultController: OsTokenVaultController, + osTokenConfig: OsTokenConfig, validatorsRegistry: Contract + let vaultImpl: string let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] beforeEach('deploy fixture', async () => { - ;[holder, receiver, admin, other] = (await (ethers as any).getSigners()).slice(1, 5) - ;({ - createEthVault: createVault, - createEthVaultMock: createVaultMock, + ;[holderV1, holderV2, receiver, admin, other] = (await (ethers as any).getSigners()).slice(1, 6) + const fixture = await loadFixture(ethVaultFixture) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + sharedMevEscrow = fixture.sharedMevEscrow + createVault = fixture.createEthVault + createVaultMock = fixture.createEthVaultMock + vaultsRegistry = fixture.vaultsRegistry + osTokenVaultController = fixture.osTokenVaultController + osTokenConfig = fixture.osTokenConfig + vaultImpl = await fixture.ethVaultFactory.implementation() + + const vaultV1 = await deployEthVaultV1( + await getEthVaultV1Factory(), + admin, keeper, + vaultsRegistry, validatorsRegistry, + osTokenVaultController, + osTokenConfig, sharedMevEscrow, - } = await loadFixture(ethVaultFixture)) - vault = await createVault( - admin, - { + encodeEthVaultInitParams({ capacity, feePercent, metadataIpfsHash, - }, - false, - true + }) ) - admin = await ethers.getImpersonatedSigner(await vault.admin()) - - const tx = await vault - .connect(holder) - .deposit(holder.address, referrer, { value: holderAssets }) - holderShares = await extractDepositShares(tx) + expect(await vaultV1.version()).to.be.eq(1) + + // create v1 position + await collateralizeEthV1Vault(vaultV1, keeper, validatorsRegistry, admin) + let tx = await vaultV1 + .connect(holderV1) + .deposit(holderV1.address, referrer, { value: holderV1Assets }) + holderV1Shares = await extractDepositShares(tx) + tx = await vaultV1.connect(holderV1).enterExitQueue(holderV1Shares, holderV1.address) + positionTicketV1 = await extractExitPositionTicket(tx) + timestampV1 = await getBlockTimestamp(tx) + + await upgradeVaultToV2(vaultV1, vaultImpl) + vault = EthVault__factory.connect(await vaultV1.getAddress(), admin) + expect(await vault.version()).to.be.eq(2) + + // create v2 position + tx = await vault + .connect(holderV2) + .deposit(holderV2.address, referrer, { value: holderV2Assets }) + tx = await vault + .connect(holderV2) + .enterExitQueue(await extractDepositShares(tx), holderV2.address) + positionTicketV2 = await extractExitPositionTicket(tx) + timestampV2 = await getBlockTimestamp(tx) + expect(positionTicketV2).to.be.eq(positionTicketV1 + holderV1Shares) }) - describe('redeem', () => { - it('fails with not enough balance', async () => { - await setBalance(await vault.getAddress(), 0n) - await expect( - vault.connect(holder).redeem(holderShares, receiver.address) - ).to.be.revertedWithCustomError(vault, 'InsufficientAssets') - }) - - it('fails for sender other than owner without approval', async () => { - await expect( - vault.connect(other).redeem(holderShares, receiver.address) - ).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW) - }) - - it('fails for shares larger than balance', async () => { - const newBalance = holderShares + 1n - await setBalance(await vault.getAddress(), newBalance) - await expect( - vault.connect(holder).redeem(newBalance, receiver.address) - ).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW) - }) - - it('fails for zero address receiver', async () => { - const newBalance = holderShares + 1n - await setBalance(await vault.getAddress(), newBalance) - await expect( - vault.connect(holder).redeem(newBalance, ZERO_ADDRESS) - ).to.be.revertedWithCustomError(vault, 'ZeroAddress') - }) - - it('fails for zero shares', async () => { - await expect(vault.connect(holder).redeem(0, holder.address)).to.be.revertedWithCustomError( - vault, - 'InvalidShares' - ) - }) - - it('does not overflow', async () => { - const vault: EthVaultMock = await createVaultMock(admin, { + it('works for not collateralized vault', async () => { + const vault = await createVault( + admin, + { capacity, feePercent, metadataIpfsHash, - }) - await vault.resetSecurityDeposit() - await vault.connect(holder).deposit(holder.address, referrer, { value: holderAssets }) - - const receiverBalanceBefore = await ethers.provider.getBalance(receiver.address) - - await setBalance(await vault.getAddress(), MAX_UINT128) - await vault._setTotalAssets(MAX_UINT128) - - await vault.connect(holder).redeem(holderShares, receiver.address) - expect(await vault.totalAssets()).to.be.eq(0) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + MAX_UINT128 - ) - }) - - it('fails for collateralized', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await expect( - vault.connect(holder).redeem(holderShares, receiver.address) - ).to.be.revertedWithCustomError(vault, 'Collateralized') - }) - - it('redeem transfers assets to receiver', async () => { - const receiverBalanceBefore = await ethers.provider.getBalance(receiver.address) - const receipt = await vault.connect(holder).redeem(holderShares, receiver.address) - await expect(receipt) - .to.emit(vault, 'Redeemed') - .withArgs(holder.address, receiver.address, holderAssets, holderShares) - - expect(await vault.totalAssets()).to.be.eq(SECURITY_DEPOSIT) - expect(await vault.totalShares()).to.be.eq(SECURITY_DEPOSIT) - expect(await vault.getShares(holder.address)).to.be.eq(0) - expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(SECURITY_DEPOSIT) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + holderAssets - ) + }, + false, + true + ) + let tx = await vault + .connect(holderV2) + .deposit(holderV2.address, referrer, { value: holderV2Assets }) + const shares = await extractDepositShares(tx) + tx = await vault.connect(holderV2).enterExitQueue(shares, holderV2.address) + const positionTicket = await extractExitPositionTicket(tx) + const timestamp = await getBlockTimestamp(tx) + await increaseTime(EXITING_ASSETS_MIN_DELAY) - await snapshotGasCost(receipt) - }) + const balanceBefore = await ethers.provider.getBalance(holderV2.address) + await expect(vault.connect(holderV2).claimExitedAssets(positionTicket, timestamp, 0n)) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(holderV2.address, 0n, holderV2Assets) + expect(await ethers.provider.getBalance(holderV2.address)).to.be.greaterThan( + balanceBefore + holderV2Assets - parseEther('0.0001') // gas + ) }) describe('enter exit queue', () => { + let holder: Wallet + let holderShares: bigint + const holderAssets = parseEther('3') + beforeEach(async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + holder = holderV2 + const tx = await vault + .connect(holder) + .deposit(holder.address, referrer, { value: holderAssets }) + holderShares = await extractDepositShares(tx) }) - it('fails with 0 shares', async () => { + it('fails with zero shares', async () => { await expect( vault.connect(holder).enterExitQueue(0, receiver.address) ).to.be.revertedWithCustomError(vault, 'InvalidShares') @@ -171,25 +178,16 @@ describe('EthVault - withdraw', () => { ).to.be.revertedWithCustomError(vault, 'ZeroAddress') }) - it('fails for not collateralized', async () => { - const newVault = await createVault( - admin, - { - capacity, - feePercent, - metadataIpfsHash, - }, - false, - true - ) - await newVault.connect(holder).deposit(holder.address, referrer, { value: holderAssets }) - await setBalance(await vault.getAddress(), 0n) + it('fails when not harvested', async () => { + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + await updateRewards(keeper, [vaultReward]) + await updateRewards(keeper, [vaultReward]) await expect( - newVault.connect(holder).enterExitQueue(holderShares, receiver.address) - ).to.be.revertedWithCustomError(vault, 'NotCollateralized') + vault.connect(holder).enterExitQueue(holderShares, receiver.address) + ).to.be.revertedWithCustomError(vault, 'NotHarvested') }) - it('fails for sender other than owner without approval', async () => { + it('fails for sender other than owner', async () => { await expect( vault.connect(other).enterExitQueue(holderShares, receiver.address) ).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW) @@ -201,42 +199,304 @@ describe('EthVault - withdraw', () => { ).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW) }) - it('locks shares for the time of exit', async () => { - expect(await vault.queuedShares()).to.be.eq(0) + it('locks assets for the time of exit', async () => { + expect(await vault.totalExitingAssets()).to.be.eq(holderV2Assets) expect(await vault.getShares(holder.address)).to.be.eq(holderShares) expect(await vault.getShares(await vault.getAddress())).to.be.eq(SECURITY_DEPOSIT) + const totalAssetsBefore = await vault.totalAssets() + const totalSharesBefore = await vault.totalShares() + const receipt = await vault.connect(holder).enterExitQueue(holderShares, receiver.address) + const positionTicket = await extractExitPositionTicket(receipt) + const timestamp = await getBlockTimestamp(receipt) await expect(receipt) .to.emit(vault, 'ExitQueueEntered') - .withArgs(holder.address, receiver.address, validatorDeposit, holderShares) + .withArgs(holder.address, receiver.address, positionTicket, holderAssets) - expect(await vault.queuedShares()).to.be.eq(holderShares) + expect(await vault.totalAssets()).to.be.eq(totalAssetsBefore - holderAssets) + expect(await vault.totalShares()).to.be.eq(totalSharesBefore - holderShares) + expect(await vault.totalExitingAssets()).to.be.eq(holderAssets + holderV2Assets) expect(await vault.getShares(holder.address)).to.be.eq(0) + expect(await vault.getShares(await vault.getAddress())).to.be.eq(SECURITY_DEPOSIT) + const result = await vault.calculateExitedAssets( + receiver.address, + positionTicket, + timestamp, + 0 + ) + expect(result.exitedAssets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.leftTickets).to.eq(holderAssets) await snapshotGasCost(receipt) }) }) + describe('calculate exited assets', () => { + it('returns zero with invalid exit request', async () => { + let result = await vault.calculateExitedAssets( + other.address, + positionTicketV1, + timestampV1, + 0n + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + + result = await vault.calculateExitedAssets(other.address, positionTicketV2, timestampV2, 0n) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + }) + + it('returns zero when delay has not passed', async () => { + let result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + 0n + ) + expect(result.leftTickets).to.eq(holderV1Shares) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + + result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(holderV2Assets) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + }) + + it('returns zero with invalid checkpoint index', async () => { + await increaseTime(EXITING_ASSETS_MIN_DELAY) + const vaultAddress = await vault.getAddress() + const vaultReward = getHarvestParams(vaultAddress, 0n, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + const chkIndex = await vault.getExitQueueIndex(positionTicketV1) + const result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + chkIndex + 1n + ) + expect(result.leftTickets).to.eq(holderV1Shares) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + }) + + it('works with partial withdrawals', async () => { + await increaseTime(EXITING_ASSETS_MIN_DELAY) + const vaultAddress = await vault.getAddress() + const vaultReward = getHarvestParams(vaultAddress, 0n, 0n) + + // no assets are available + await setBalance(vaultAddress, 0n) + let tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + expect(await vault.getExitQueueIndex(positionTicketV1)).to.eq(-1) + expect(await vault.getExitQueueIndex(positionTicketV2)).to.eq(-1) + expect(await vault.totalExitingAssets()).to.eq(holderV2Assets) + let result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(holderV2Assets) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + + // only half of position v1 assets are available + const halfHolderV1Assets = holderV1Assets / 2n + const halfHolderV1Shares = holderV1Shares / 2n + await setBalance(vaultAddress, halfHolderV1Assets) + tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + let chkIndex = await vault.getExitQueueIndex(positionTicketV1) + expect(chkIndex).to.be.greaterThan(0) + result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + chkIndex + ) + expect(result.leftTickets).to.eq(halfHolderV1Shares) + expect(result.exitedTickets).to.eq(halfHolderV1Shares) + expect(result.exitedAssets).to.eq(halfHolderV1Assets) + + expect(await vault.getExitQueueIndex(positionTicketV2)).to.eq(-1) + result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(holderV2Assets) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + + // all position v1 assets are available + await setBalance(vaultAddress, holderV1Assets) + tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + chkIndex = await vault.getExitQueueIndex(positionTicketV1) + expect(chkIndex).to.be.greaterThan(0) + result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + chkIndex + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(holderV1Shares) + expect(result.exitedAssets).to.eq(holderV1Assets) + + expect(await vault.getExitQueueIndex(positionTicketV2)).to.eq(-1) + result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(holderV2Assets) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + + // half holder v2 assets are available + const halfHolderV2Assets = holderV2Assets / 2n + await setBalance(vaultAddress, holderV1Assets + halfHolderV2Assets) + tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + chkIndex = await vault.getExitQueueIndex(positionTicketV1) + expect(chkIndex).to.be.greaterThan(0) + result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + chkIndex + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(holderV1Shares) + expect(result.exitedAssets).to.eq(holderV1Assets) + + expect(await vault.getExitQueueIndex(positionTicketV2)).to.eq(0) + result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(halfHolderV2Assets) + expect(result.exitedTickets).to.eq(halfHolderV2Assets) + expect(result.exitedAssets).to.eq(halfHolderV2Assets) + + // holder v2 all assets are available + await setBalance(vaultAddress, holderV1Assets + holderV2Assets) + tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + chkIndex = await vault.getExitQueueIndex(positionTicketV1) + expect(chkIndex).to.be.greaterThan(0) + result = await vault.calculateExitedAssets( + holderV1.address, + positionTicketV1, + timestampV1, + chkIndex + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(holderV1Shares) + expect(result.exitedAssets).to.eq(holderV1Assets) + + expect(await vault.getExitQueueIndex(positionTicketV2)).to.eq(0) + result = await vault.calculateExitedAssets( + holderV2.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(holderV2Assets) + expect(result.exitedAssets).to.eq(holderV2Assets) + }) + }) + describe('update exit queue', () => { + let vault: Contract + let holder: Wallet, admin: Wallet + let holderShares: bigint + const holderAssets = parseEther('3') let harvestParams: IKeeperRewards.HarvestParamsStruct + let positionTicket: bigint beforeEach(async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await vault.connect(holder).enterExitQueue(holderShares, receiver.address) - const tree = await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) + holder = holderV1 + admin = receiver + vault = await deployEthVaultV1( + await getEthVaultV1Factory(), + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthVaultInitParams({ + capacity, + feePercent, + metadataIpfsHash, + }) + ) + await collateralizeEthV1Vault(vault, keeper, validatorsRegistry, admin) + let tx = await vault + .connect(holder) + .deposit(holder.address, referrer, { value: holderAssets }) + holderShares = await extractDepositShares(tx) + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + const tree = await updateRewards(keeper, [vaultReward]) harvestParams = { rewardsRoot: tree.root, - reward: 0n, - unlockedMevReward: 0n, - proof: getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: 0n, - unlockedMevReward: 0n, - }), + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), } + tx = await vault.connect(holder).enterExitQueue(holderShares, holder.address) + positionTicket = await extractExitPositionTicket(tx) }) it('skips with 0 queued shares', async () => { @@ -262,19 +522,14 @@ describe('EthVault - withdraw', () => { it('skips with 0 burned assets', async () => { const totalAssets = await vault.totalAssets() const penalty = totalAssets - totalAssets * 2n - const tree = await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: penalty, unlockedMevReward: 0n }, - ]) + const vaultReward = getHarvestParams(await vault.getAddress(), penalty, 0n) + const tree = await updateRewards(keeper, [vaultReward]) await expect( vault.updateState({ rewardsRoot: tree.root, - reward: penalty, - unlockedMevReward: 0n, - proof: getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: penalty, - unlockedMevReward: 0n, - }), + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), }) ).to.not.emit(vault, 'CheckpointCreated') }) @@ -308,210 +563,237 @@ describe('EthVault - withdraw', () => { await snapshotGasCost(receipt) }) - }) - - it('get checkpoint index works with many checkpoints', async () => { - const vault: EthVaultMock = await createVaultMock(admin, { - capacity, - feePercent, - metadataIpfsHash, - }) - - // collateralize vault by registering validator - await vault.connect(holder).deposit(holder.address, referrer, { value: validatorDeposit }) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) - const receipt = await vault.connect(holder).enterExitQueue(holderShares, receiver.address) - const positionTicket = await extractExitPositionTicket(receipt) - - // create checkpoints every day for 10 years - for (let i = 1; i <= 3650; i++) { - await setBalance(await vault.getAddress(), BigInt(i)) - await increaseTime(ONE_DAY) - const rewardsTree = await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) - const proof = getRewardsRootProof(rewardsTree, { - vault: await vault.getAddress(), - reward: 0n, - unlockedMevReward: 0n, - }) - await expect( - vault.updateState({ - rewardsRoot: rewardsTree.root, + it('get checkpoint index works with many checkpoints', async () => { + // create checkpoints every day for 10 years + for (let i = 1; i <= 3650; i++) { + await setBalance(await vault.getAddress(), BigInt(i)) + await increaseTime(ONE_DAY) + const rewardsTree = await updateRewards(keeper, [ + { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, + ]) + const proof = getRewardsRootProof(rewardsTree, { + vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n, - proof, }) - ).to.emit(vault, 'CheckpointCreated') - } - await snapshotGasCost(await vault.getGasCostOfGetExitQueueIndex(positionTicket)) + await expect( + vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: 0n, + unlockedMevReward: 0n, + proof, + }) + ).to.emit(vault, 'CheckpointCreated') + } + const chkIndex = await vault.getExitQueueIndex(positionTicket) + expect(chkIndex).to.be.greaterThan(0) + }) }) describe('claim exited assets', () => { - let receiverBalanceBefore: bigint - let positionTicket: bigint - let timestamp: number let harvestParams: IKeeperRewards.HarvestParamsStruct beforeEach(async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const response = await vault.connect(holder).enterExitQueue(holderShares, receiver.address) - positionTicket = await extractExitPositionTicket(response) - timestamp = await getBlockTimestamp(response) - receiverBalanceBefore = await ethers.provider.getBalance(receiver.address) - - const tree = await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + const tree = await updateRewards(keeper, [vaultReward]) harvestParams = { rewardsRoot: tree.root, - reward: 0n, - unlockedMevReward: 0n, - proof: getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: 0n, - unlockedMevReward: 0n, - }), + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), } }) - it('returns zero with no queued shares', async () => { + it('fails with invalid exit request', async () => { await increaseTime(EXITING_ASSETS_MIN_DELAY) await vault.updateState(harvestParams) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) - const result = await vault - .connect(other) - .claimExitedAssets.staticCall(positionTicket, timestamp, checkpointIndex) - expect(result.newPositionTicket).to.be.eq(positionTicket) - expect(result.claimedAssets).to.be.eq(0) + let result = await vault.calculateExitedAssets( + other.address, + positionTicketV2, + timestampV2, + 0n + ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) await expect( - vault.connect(other).claimExitedAssets(positionTicket, timestamp, checkpointIndex) - ).to.not.emit(vault, 'ExitedAssetsClaimed') - }) + vault.connect(other).claimExitedAssets(positionTicketV2, timestampV2, 0n) + ).to.revertedWithCustomError(vault, 'ExitRequestNotProcessed') - it('returns -1 for unknown checkpoint index', async () => { - expect(await vault.getExitQueueIndex(validatorDeposit)).to.be.eq(-1) + result = await vault.calculateExitedAssets(other.address, positionTicketV2, timestampV2, 0n) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + await expect( + vault.connect(other).claimExitedAssets(positionTicketV2, timestampV2, 0n) + ).to.revertedWithCustomError(vault, 'ExitRequestNotProcessed') }) - it('returns 0 with checkpoint index larger than checkpoints array', async () => { + it('fails with invalid timestamp', async () => { await increaseTime(EXITING_ASSETS_MIN_DELAY) - const result = await vault - .connect(receiver) - .claimExitedAssets.staticCall(positionTicket, timestamp, 1) - expect(result.newPositionTicket).to.be.eq(validatorDeposit) - expect(result.claimedAssets).to.be.eq(0) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq(receiverBalanceBefore) - expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq( - holderAssets + SECURITY_DEPOSIT + await vault.updateState(harvestParams) + const result = await vault.calculateExitedAssets( + other.address, + positionTicketV2, + timestampV2, + 0n ) + expect(result.leftTickets).to.eq(0) + expect(result.exitedTickets).to.eq(0) + expect(result.exitedAssets).to.eq(0) + await expect( + vault.connect(holderV2).claimExitedAssets(positionTicketV2, timestampV1, 0n) + ).to.be.revertedWithCustomError(vault, 'ExitRequestNotProcessed') }) - it('fails with invalid checkpoint index', async () => { - await vault.updateState(harvestParams) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) - - await vault.connect(holder).deposit(holder.address, referrer, { value: holderAssets * 2n }) - let response = await vault.connect(holder).enterExitQueue(holderShares, receiver.address) - const positionTicket2 = await extractExitPositionTicket(response) - const timestamp2 = await getBlockTimestamp(response) - + it('fails when not harvested', async () => { await increaseTime(EXITING_ASSETS_MIN_DELAY) + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + await updateRewards(keeper, [vaultReward]) + await expect( + vault.connect(holderV2).claimExitedAssets(positionTicketV2, timestampV2, 0n) + ).to.be.revertedWithCustomError(vault, 'NotHarvested') + }) - // checkpointIndex is lower than positionTicket + it('fails with invalid index', async () => { + await increaseTime(EXITING_ASSETS_MIN_DELAY) await expect( - vault.connect(receiver).claimExitedAssets(positionTicket2, timestamp2, checkpointIndex) + vault.connect(holderV1).claimExitedAssets(positionTicketV1, timestampV1, 0n) ).to.be.revertedWithCustomError(vault, 'InvalidCheckpointIndex') - await increaseTime(ONE_DAY) - await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) - await vault.updateState(harvestParams) - - response = await vault.connect(holder).enterExitQueue(holderShares, receiver.address) - const positionTicket3 = await extractExitPositionTicket(response) - await increaseTime(ONE_DAY) - await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) - await vault.updateState(harvestParams) + }) - const checkpointIndexThree = await vault.getExitQueueIndex(positionTicket3) - // checkpointIndex is higher than positionTicket + it('applies penalty when rate decreases', async () => { + const halfHolderV2Assets = holderV2Assets / 2n + const halfSecurityDeposit = SECURITY_DEPOSIT / 2n await increaseTime(EXITING_ASSETS_MIN_DELAY) + // user v1 assets exited + await vault.updateState(harvestParams) + const vaultReward = getHarvestParams(await vault.getAddress(), -halfHolderV2Assets, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + unlockedMevReward: vaultReward.unlockedMevReward, + reward: vaultReward.reward, + proof: getRewardsRootProof(tree, vaultReward), + }) await expect( - vault.connect(receiver).claimExitedAssets(positionTicket, timestamp, checkpointIndexThree) - ).to.be.revertedWithCustomError(vault, 'InvalidCheckpointIndex') + vault + .connect(holderV1) + .claimExitedAssets( + positionTicketV1, + timestampV1, + await vault.getExitQueueIndex(positionTicketV1) + ) + ) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(holderV1.address, 0n, holderV1Assets) + await expect(vault.connect(holderV2).claimExitedAssets(positionTicketV2, timestampV2, 0n)) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(holderV2.address, 0n, halfHolderV2Assets + halfSecurityDeposit) + expect(await vault.totalExitingAssets()).to.be.eq(0) }) - it('fails with invalid timestamp', async () => { - await vault.updateState(harvestParams) + it('applies penalty to all exiting assets', async () => { + const vault = await createVaultMock(admin as Wallet, { + capacity, + feePercent: 0, + metadataIpfsHash, + }) + await vault.resetSecurityDeposit() + let tx = await vault.deposit(holderV2.address, referrer, { value: holderV2Assets }) + const shares = await extractDepositShares(tx) + tx = await vault.connect(holderV2).enterExitQueue(shares, holderV2.address) + const positionTicket = await extractExitPositionTicket(tx) + const timestamp = await getBlockTimestamp(tx) + await increaseTime(EXITING_ASSETS_MIN_DELAY) + + expect(await vault.totalExitingAssets()).to.be.eq(holderV2Assets) + expect(await vault.getShares(holderV2.address)).to.be.eq(0) + expect(await vault.getShares(await vault.getAddress())).to.be.eq(0) + expect(await vault.totalAssets()).to.be.eq(0) + expect(await vault.totalShares()).to.be.eq(0) + + // penalty received + const halfHolderV2Assets = holderV2Assets / 2n + const vaultReward = getHarvestParams(await vault.getAddress(), -halfHolderV2Assets, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + await vault.updateState({ + rewardsRoot: tree.root, + unlockedMevReward: vaultReward.unlockedMevReward, + reward: vaultReward.reward, + proof: getRewardsRootProof(tree, vaultReward), + }) + await expect( vault - .connect(receiver) + .connect(holderV2) .claimExitedAssets( positionTicket, timestamp, await vault.getExitQueueIndex(positionTicket) ) - ).to.be.revertedWithCustomError(vault, 'ClaimTooEarly') + ) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(holderV2.address, 0n, halfHolderV2Assets) + expect(await vault.totalExitingAssets()).to.be.eq(0) }) it('for single user in single checkpoint', async () => { await vault.updateState(harvestParams) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) + const checkpointIndex = await vault.getExitQueueIndex(positionTicketV1) await increaseTime(EXITING_ASSETS_MIN_DELAY) + const holderV1AssetsBefore = await ethers.provider.getBalance(holderV1.address) const receipt = await vault - .connect(receiver) - .claimExitedAssets(positionTicket, timestamp, checkpointIndex) + .connect(holderV1) + .claimExitedAssets(positionTicketV1, timestampV1, checkpointIndex) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(receiver.address, positionTicket, 0, holderAssets) + .withArgs(holderV1.address, 0, holderV1Assets) const tx = (await receipt.wait()) as any const gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + holderAssets - gasUsed + expect(await ethers.provider.getBalance(holderV1.address)).to.be.eq( + holderV1AssetsBefore + holderV1Assets - gasUsed ) - expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(SECURITY_DEPOSIT) await snapshotGasCost(receipt) }) it('for single user in multiple checkpoints in single transaction', async () => { - const halfHolderAssets = holderAssets / 2n - const halfHolderShares = holderShares / 2n + const halfHolderAssets = holderV1Assets / 2n + const halfHolderShares = holderV1Shares / 2n // create two checkpoints await setBalance(await vault.getAddress(), halfHolderAssets) await expect(vault.updateState(harvestParams)) .to.emit(vault, 'CheckpointCreated') .withArgs(halfHolderShares, halfHolderAssets) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) + const checkpointIndex = await vault.getExitQueueIndex(positionTicketV1) await increaseTime(ONE_DAY) - await setBalance(await vault.getAddress(), holderAssets) - await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) + await setBalance(await vault.getAddress(), holderV1Assets) + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + await updateRewards(keeper, [vaultReward]) await expect(vault.updateState(harvestParams)) .to.emit(vault, 'CheckpointCreated') .withArgs(halfHolderShares, halfHolderAssets) await increaseTime(EXITING_ASSETS_MIN_DELAY) + const holderV1AssetsBefore = await ethers.provider.getBalance(holderV1.address) const receipt = await vault - .connect(receiver) - .claimExitedAssets(positionTicket, timestamp, checkpointIndex) + .connect(holderV1) + .claimExitedAssets(positionTicketV1, timestampV1, checkpointIndex) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(receiver.address, positionTicket, 0, holderAssets) + .withArgs(holderV1.address, 0, holderV1Assets) const tx = (await receipt.wait()) as any const gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + holderAssets - gasUsed + expect(await ethers.provider.getBalance(holderV1.address)).to.be.eq( + holderV1AssetsBefore + holderV1Assets - gasUsed ) expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(0) @@ -519,30 +801,31 @@ describe('EthVault - withdraw', () => { }) it('for single user in multiple checkpoints in multiple transactions', async () => { - const halfHolderAssets = holderAssets / 2n - const halfHolderShares = holderShares / 2n + const halfHolderAssets = holderV1Assets / 2n + const halfHolderShares = holderV1Shares / 2n // create first checkpoint await setBalance(await vault.getAddress(), halfHolderAssets) await expect(vault.updateState(harvestParams)) .to.emit(vault, 'CheckpointCreated') .withArgs(halfHolderShares, halfHolderAssets) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) + const checkpointIndex = await vault.getExitQueueIndex(positionTicketV1) await increaseTime(EXITING_ASSETS_MIN_DELAY) + const holderV1AssetsBefore = await ethers.provider.getBalance(holderV1.address) let receipt = await vault - .connect(receiver) - .claimExitedAssets(positionTicket, timestamp, checkpointIndex) + .connect(holderV1) + .claimExitedAssets(positionTicketV1, timestampV1, checkpointIndex) const newPositionTicket = validatorDeposit + halfHolderShares await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(receiver.address, positionTicket, newPositionTicket, halfHolderAssets) + .withArgs(holderV1.address, newPositionTicket, halfHolderAssets) let tx = (await receipt.wait()) as any let gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + halfHolderAssets - gasUsed + expect(await ethers.provider.getBalance(holderV1.address)).to.be.eq( + holderV1AssetsBefore + halfHolderAssets - gasUsed ) await snapshotGasCost(receipt) @@ -559,16 +842,16 @@ describe('EthVault - withdraw', () => { const newCheckpointIndex = await vault.getExitQueueIndex(newPositionTicket) receipt = await vault - .connect(receiver) - .claimExitedAssets(newPositionTicket, timestamp, newCheckpointIndex) + .connect(holderV1) + .claimExitedAssets(newPositionTicket, timestampV1, newCheckpointIndex) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(receiver.address, newPositionTicket, 0, halfHolderAssets) + .withArgs(holderV1.address, 0, halfHolderAssets) tx = (await receipt.wait()) as any gasUsed += BigInt(tx.cumulativeGasUsed * tx.gasPrice) - expect(await ethers.provider.getBalance(receiver.address)).to.be.eq( - receiverBalanceBefore + holderAssets - gasUsed + expect(await ethers.provider.getBalance(holderV1.address)).to.be.eq( + holderV1AssetsBefore + holderV1Assets - gasUsed ) expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(0) @@ -576,15 +859,27 @@ describe('EthVault - withdraw', () => { }) it('for multiple users in single checkpoint', async () => { - // harvests the previous queued position - await vault.updateState(harvestParams) - const checkpointIndex = await vault.getExitQueueIndex(positionTicket) - await increaseTime(EXITING_ASSETS_MIN_DELAY) - await vault.connect(receiver).claimExitedAssets(positionTicket, timestamp, checkpointIndex) + const admin = holderV2 + const vault = await deployEthVaultV1( + await getEthVaultV1Factory(), + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + encodeEthVaultInitParams({ + capacity, + feePercent, + metadataIpfsHash, + }) + ) + await collateralizeEthV1Vault(vault, keeper, validatorsRegistry, admin) - const shares = holderShares - const assets = holderAssets - const user1 = holder + const shares = parseEther('1') + const assets = parseEther('1') + const user1 = holderV1 const user2 = receiver await vault.connect(user1).deposit(user1.address, referrer, { value: assets }) @@ -601,9 +896,14 @@ describe('EthVault - withdraw', () => { const user2BalanceBefore = await ethers.provider.getBalance(user2.address) await increaseTime(ONE_DAY) - await updateRewards(keeper, [ - { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, - ]) + const vaultReward = getHarvestParams(await vault.getAddress(), 0n, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + const harvestParams = { + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + } await expect(vault.connect(other).updateState(harvestParams)) .to.emit(vault, 'CheckpointCreated') .withArgs(shares * 2n, assets * 2n) @@ -655,14 +955,13 @@ describe('EthVault - withdraw', () => { metadataIpfsHash, }) await vault.resetSecurityDeposit() - const alice = holder - const bob = other + const alice = holderV1 + const bob = holderV2 let sharedMevEscrowBalance = await ethers.provider.getBalance( await sharedMevEscrow.getAddress() ) // collateralize vault by registering validator - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) await vault._setTotalAssets(0) await vault._setTotalShares(0) @@ -672,25 +971,37 @@ describe('EthVault - withdraw', () => { let bobAssets = 0n let totalAssets = 0n let totalShares = 0n - let queuedShares = 0n - let unclaimedAssets = 0n - let latestPositionTicket = validatorDeposit + let totalExitingAssets = 0n + let latestPositionTicket = 0n let vaultLiquidAssets = 0n let totalReward = 0n let totalUnlockedMevReward = 0n const checkVaultState = async () => { - expect(await vault.getShares(alice.address)).to.be.eq(aliceShares) - expect(await vault.getShares(bob.address)).to.be.eq(bobShares) - expect(await vault.convertToAssets(aliceShares)).to.be.eq(aliceAssets) - expect(await vault.convertToAssets(bobShares)).to.be.eq(bobAssets) - expect(await vault.totalShares()).to.be.eq(totalShares) + expect(await vault.getShares(alice.address)).to.be.eq(aliceShares, 'Alice shares mismatch') + expect(await vault.getShares(bob.address)).to.be.eq(bobShares, 'Bob shares mismatch') + expect(await vault.convertToAssets(aliceShares)).to.be.eq( + aliceAssets, + 'Alice convertToAssets mismatch' + ) + expect(await vault.convertToAssets(bobShares)).to.be.eq( + bobAssets, + 'Bob convertToAssets mismatch' + ) + expect(await vault.totalShares()).to.be.eq(totalShares, 'Total shares mismatch') expect(await ethers.provider.getBalance(await sharedMevEscrow.getAddress())).to.be.eq( - sharedMevEscrowBalance + sharedMevEscrowBalance, + 'Shared MEV escrow balance mismatch' + ) + expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq( + vaultLiquidAssets, + 'Vault liquid assets mismatch' + ) + expect(await vault.totalAssets()).to.be.eq(totalAssets, 'Total assets mismatch') + expect(await vault.totalExitingAssets()).to.be.eq( + totalExitingAssets, + 'Total exiting assets mismatch' ) - expect(await ethers.provider.getBalance(await vault.getAddress())).to.be.eq(vaultLiquidAssets) - expect(await vault.totalAssets()).to.be.eq(totalAssets) - expect(await vault.queuedShares()).to.be.eq(queuedShares) } // 1. Alice deposits 2000 ETH (mints 2000 shares) @@ -718,23 +1029,18 @@ describe('EthVault - withdraw', () => { totalReward += 3000n vaultLiquidAssets += 1800n totalUnlockedMevReward += 1800n - let tree = await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - let proof = getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }) + let vaultReward = getHarvestParams( + await vault.getAddress(), + totalReward, + totalUnlockedMevReward + ) + let tree = await updateRewards(keeper, [vaultReward]) + let proof = getRewardsRootProof(tree, vaultReward) await setBalance(await sharedMevEscrow.getAddress(), 1800n) await vault.updateState({ rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, proof, }) aliceAssets += 1000n @@ -770,22 +1076,13 @@ describe('EthVault - withdraw', () => { vaultLiquidAssets += 1800n totalUnlockedMevReward += 1800n await setBalance(await sharedMevEscrow.getAddress(), 1800n) - tree = await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - proof = getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }) + vaultReward = getHarvestParams(await vault.getAddress(), totalReward, totalUnlockedMevReward) + tree = await updateRewards(keeper, [vaultReward]) + proof = getRewardsRootProof(tree, vaultReward) await vault.updateState({ rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, proof, }) @@ -799,198 +1096,126 @@ describe('EthVault - withdraw', () => { let alicePositionTicket = await extractExitPositionTicket(response) let aliceTimestamp = await getBlockTimestamp(response) - // alice withdraws assets - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - await vault.updateState({ - rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - proof, - }) - await increaseTime(EXITING_ASSETS_MIN_DELAY) - await vault - .connect(alice) - .claimExitedAssets( - alicePositionTicket, - aliceTimestamp, - await vault.getExitQueueIndex(alicePositionTicket) - ) - aliceShares -= 1333n - aliceAssets -= 2428n - bobAssets -= 1n // rounding error + aliceAssets -= 2427n totalAssets -= 2427n - vaultLiquidAssets -= 2427n - totalShares -= 1332n + totalExitingAssets += 2427n + totalShares -= 1333n expect(alicePositionTicket).to.eq(latestPositionTicket) - latestPositionTicket = validatorDeposit + 1333n - queuedShares += 1n + latestPositionTicket = 2427n await checkVaultState() - // 8. Bob enters exit queue with 1608 assets (2928 shares) + // 8. Alice withdraws assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) + expect(await vault.getExitQueueIndex(alicePositionTicket)).to.be.eq(0) + await vault.connect(alice).claimExitedAssets(alicePositionTicket, aliceTimestamp, 0n) + + vaultLiquidAssets -= 2427n + totalExitingAssets -= 2427n + + await checkVaultState() + + // 9. Bob enters exit queue with 1608 shares (2928 assets) response = await vault.connect(bob).enterExitQueue(1608, bob.address) let bobPositionTicket = await extractExitPositionTicket(response) let bobTimestamp = await getBlockTimestamp(response) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - await vault.updateState({ - rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - proof, - }) - await increaseTime(EXITING_ASSETS_MIN_DELAY) - await vault - .connect(alice) - .claimExitedAssets( - alicePositionTicket, - aliceTimestamp, - await vault.getExitQueueIndex(alicePositionTicket) - ) - await vault - .connect(bob) - .claimExitedAssets( - bobPositionTicket, - bobTimestamp, - await vault.getExitQueueIndex(bobPositionTicket) - ) - bobShares -= 1608n - bobAssets -= 2929n - totalAssets -= 2929n - vaultLiquidAssets -= 2927n + bobAssets -= 2928n + totalAssets -= 2928n + totalExitingAssets += 2928n totalShares -= 1608n expect(bobPositionTicket).to.eq(latestPositionTicket) - latestPositionTicket = latestPositionTicket + 1608n + latestPositionTicket = latestPositionTicket + 2928n await checkVaultState() - // 9. Most the Vault's assets are staked + // 10. Bob withdraws assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) + expect(await vault.getExitQueueIndex(bobPositionTicket)).to.be.eq(0) + await vault.connect(bob).claimExitedAssets(bobPositionTicket, bobTimestamp, 0n) + vaultLiquidAssets -= 2928n + totalExitingAssets -= 2928n + await checkVaultState() + + // 11. Most the Vault's assets are staked vaultLiquidAssets = 2600n await setBalance(await vault.getAddress(), 2600n) + await checkVaultState() - // 10. Alice enters exit queue with 1000 shares + // 12. Alice enters exit queue with 1000 shares (1821 assets) response = await vault.connect(alice).enterExitQueue(1000, alice.address) alicePositionTicket = await extractExitPositionTicket(response) aliceTimestamp = await getBlockTimestamp(response) await expect(response) .to.emit(vault, 'ExitQueueEntered') - .withArgs(alice.address, alice.address, alicePositionTicket, 1000) + .withArgs(alice.address, alice.address, alicePositionTicket, 1821) - aliceShares -= 1000n // rounding error + aliceShares -= 1000n + totalShares -= 1000n + totalAssets -= 1821n aliceAssets -= 1821n - queuedShares += 1000n + totalExitingAssets += 1821n expect(alicePositionTicket).to.eq(latestPositionTicket) - latestPositionTicket = latestPositionTicket + 1000n + latestPositionTicket = latestPositionTicket + 1821n await checkVaultState() - // 11. Bob enters exit queue with 4393 shares + // 13. Bob enters exit queue with 4393 shares (8000 assets) response = await vault.connect(bob).enterExitQueue(4393n, bob.address) bobPositionTicket = await extractExitPositionTicket(response) bobTimestamp = await getBlockTimestamp(response) await expect(response) .to.emit(vault, 'ExitQueueEntered') - .withArgs(bob.address, bob.address, bobPositionTicket, 4393) + .withArgs(bob.address, bob.address, bobPositionTicket, 8000) + aliceAssets += 1n // rounding error bobShares -= 4393n - bobAssets -= 7998n - queuedShares += 4393n + bobAssets -= 8000n + totalShares -= 4393n + totalAssets -= 8000n + totalExitingAssets += 8000n expect(bobPositionTicket).to.eq(latestPositionTicket) - latestPositionTicket = latestPositionTicket + 4393n + latestPositionTicket = latestPositionTicket + 8000n await checkVaultState() - // 12. Update exit queue and transfer not staked assets to Bob and Alice - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - await expect( - vault.updateState({ - rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - proof, - }) - ) - .to.emit(vault, 'CheckpointCreated') - .withArgs(1426, 2598) - - totalAssets -= 2598n - totalShares -= 1426n - queuedShares -= 1426n - unclaimedAssets += 2598n - await checkVaultState() - - // 13. Vault mutates by +5000 shares + // 14. Vault mutates by +5000 assets totalAssets += 5000n totalReward += 5000n + aliceAssets += 5000n vaultLiquidAssets += 3000n totalUnlockedMevReward += 3000n - tree = await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) + vaultReward = getHarvestParams(await vault.getAddress(), totalReward, totalUnlockedMevReward) + tree = await updateRewards(keeper, [vaultReward]) await setBalance(await sharedMevEscrow.getAddress(), 3000n) - await expect( - vault.updateState({ - rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - proof: getRewardsRootProof(tree, { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }), - }) - ) - .to.emit(vault, 'CheckpointCreated') - .withArgs(1061, 3000) - - // update alice assets - aliceAssets += 1007n - totalShares -= 1061n - totalAssets -= 3000n - queuedShares -= 1061n - unclaimedAssets += 3000n + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + }) + await checkVaultState() // 14. Bob claims exited assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) let bobCheckpointIdx = await vault.getExitQueueIndex(bobPositionTicket) await expect( vault.connect(bob).claimExitedAssets(bobPositionTicket, bobTimestamp, bobCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(bob.address, bobPositionTicket, bobPositionTicket + 1486n, 3774n) + .withArgs(bob.address, bobPositionTicket + 3779n, 3779n) - bobPositionTicket = bobPositionTicket + 1486n - vaultLiquidAssets -= 3774n - unclaimedAssets -= 3774n + bobPositionTicket += 3779n + vaultLiquidAssets -= 3779n + totalExitingAssets -= 3779n await checkVaultState() - // 15. Alice claims exited assets + // 16. Alice claims exited assets let aliceCheckpointIdx = await vault.getExitQueueIndex(alicePositionTicket) await expect( vault @@ -998,76 +1223,58 @@ describe('EthVault - withdraw', () => { .claimExitedAssets(alicePositionTicket, aliceTimestamp, aliceCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(alice.address, alicePositionTicket, 0, 1821) + .withArgs(alice.address, 0n, 1821) vaultLiquidAssets -= 1821n - unclaimedAssets -= 1821n + totalExitingAssets -= 1821n await checkVaultState() - // 16. Alice enters exit queue with 1001 shares + // 17. Alice enters exit queue with 1001 shares response = await vault.connect(alice).enterExitQueue(1001, alice.address) alicePositionTicket = await extractExitPositionTicket(response) aliceTimestamp = await getBlockTimestamp(response) await expect(response) .to.emit(vault, 'ExitQueueEntered') - .withArgs(alice.address, alice.address, alicePositionTicket, 1001) + .withArgs(alice.address, alice.address, latestPositionTicket, 6824n) expect(alicePositionTicket).to.be.eq(latestPositionTicket) - queuedShares += 1001n aliceShares -= 1001n - aliceAssets -= 2829n + aliceAssets -= 6824n + totalShares -= 1001n + totalAssets -= 6824n + totalExitingAssets += 6824n await checkVaultState() // 17. Withdrawal of all the assets arrives - await increaseTime(ONE_DAY) - await setBalance(await vault.getAddress(), totalAssets + unclaimedAssets + 2n) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - }, - ]) - await expect( - vault.updateState({ - rewardsRoot: tree.root, - reward: totalReward, - unlockedMevReward: totalUnlockedMevReward, - proof, - }) - ).to.emit(vault, 'CheckpointCreated') - - unclaimedAssets += totalAssets + 2n - vaultLiquidAssets = unclaimedAssets - totalShares = 0n - queuedShares = 0n - totalAssets = 0n + await setBalance(await vault.getAddress(), totalExitingAssets) + vaultLiquidAssets = totalExitingAssets await checkVaultState() - // 18. Bob claims exited assets + // 19. Bob claims exited assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) bobCheckpointIdx = await vault.getExitQueueIndex(bobPositionTicket) - expect(bobCheckpointIdx).to.eq(5) await expect( vault.connect(bob).claimExitedAssets(bobPositionTicket, bobTimestamp, bobCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(bob.address, bobPositionTicket, 0, 8216) + .withArgs(bob.address, 0, 4221) - vaultLiquidAssets -= 8216n + vaultLiquidAssets -= 4221n + totalExitingAssets -= 4221n await checkVaultState() - // 19. Alice claims exited assets + // 20. Alice claims exited assets aliceCheckpointIdx = await vault.getExitQueueIndex(alicePositionTicket) - expect(aliceCheckpointIdx).to.eq(5) await expect( vault .connect(alice) .claimExitedAssets(alicePositionTicket, aliceTimestamp, aliceCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(alice.address, alicePositionTicket, 0, 2829) - vaultLiquidAssets -= 2829n + .withArgs(alice.address, 0, 6824) + vaultLiquidAssets -= 6824n + totalExitingAssets -= 6824n await checkVaultState() // 20. Check whether state is correct @@ -1077,8 +1284,7 @@ describe('EthVault - withdraw', () => { bobAssets = 0n totalAssets = 0n totalShares = 0n - queuedShares = 0n - vaultLiquidAssets = 6n + vaultLiquidAssets = 0n await checkVaultState() }) }) diff --git a/test/EthVaultFactory.spec.ts b/test/EthVaultFactory.spec.ts index adeb60a7..26c41747 100644 --- a/test/EthVaultFactory.spec.ts +++ b/test/EthVaultFactory.spec.ts @@ -188,7 +188,7 @@ describe('EthVaultFactory', () => { .withArgs(await factory.getAddress(), metadataIpfsHash) // VaultVersion - expect(await vault.version()).to.be.eq(1) + expect(await vault.version()).to.be.eq(2) expect(await vault.vaultId()).to.be.eq(toHexString(keccak256(vaultClass))) expect(await factory.implementation()).to.be.eq(await vault.implementation()) diff --git a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap new file mode 100644 index 00000000..764c4e4c --- /dev/null +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 71149, +} +`; + +exports[`EthBlocklistErc20Vault deposit deposit through receive fallback can be called by not blocked sender 1`] = ` +Object { + "calldataByteLength": 4, + "gasUsed": 78315, +} +`; + +exports[`EthBlocklistErc20Vault ejecting user blocklist manager can eject all of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 120550, +} +`; + +exports[`EthBlocklistErc20Vault ejecting user blocklist manager can eject some of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 146827, +} +`; + +exports[`EthBlocklistErc20Vault ejecting user does not fail for user with no osToken shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 120550, +} +`; + +exports[`EthBlocklistErc20Vault ejecting user does not fail for user with no vault shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 56104, +} +`; + +exports[`EthBlocklistErc20Vault mint osToken can mint from not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 174071, +} +`; + +exports[`EthBlocklistErc20Vault transfer can transfer 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 59012, +} +`; diff --git a/test/__snapshots__/EthBlocklistVault.spec.ts.snap b/test/__snapshots__/EthBlocklistVault.spec.ts.snap new file mode 100644 index 00000000..1e5fea86 --- /dev/null +++ b/test/__snapshots__/EthBlocklistVault.spec.ts.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EthBlocklistVault deposit can be called by not blocked user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 69056, +} +`; + +exports[`EthBlocklistVault deposit deposit through receive fallback can be called by not blocked sender 1`] = ` +Object { + "calldataByteLength": 4, + "gasUsed": 76519, +} +`; + +exports[`EthBlocklistVault ejecting user blocklist manager can eject all of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 118535, +} +`; + +exports[`EthBlocklistVault ejecting user blocklist manager can eject some of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 144812, +} +`; + +exports[`EthBlocklistVault ejecting user does not fail for user with no osToken shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 118535, +} +`; + +exports[`EthBlocklistVault ejecting user does not fail for user with no vault shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 55884, +} +`; + +exports[`EthBlocklistVault mint osToken can mint from not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 173861, +} +`; diff --git a/test/__snapshots__/EthErc20Vault.spec.ts.snap b/test/__snapshots__/EthErc20Vault.spec.ts.snap index a2d3174e..70aa490e 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -3,28 +3,21 @@ exports[`EthErc20Vault deposit emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68858, + "gasUsed": 68804, } `; exports[`EthErc20Vault deposit through receive fallback function emits transfer event 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 76116, + "gasUsed": 76084, } `; exports[`EthErc20Vault enter exit queue emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 89043, -} -`; - -exports[`EthErc20Vault redeem emits transfer event 1`] = ` -Object { - "calldataByteLength": 68, - "gasUsed": 60170, + "gasUsed": 96055, } `; diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index 0ce955eb..669281f9 100644 --- a/test/__snapshots__/EthFoxVault.spec.ts.snap +++ b/test/__snapshots__/EthFoxVault.spec.ts.snap @@ -3,55 +3,48 @@ exports[`EthFoxVault blocklist can be updated by blocklist manager 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 53765, + "gasUsed": 53743, } `; exports[`EthFoxVault blocklist can be updated by blocklist manager 2`] = ` Object { "calldataByteLength": 68, - "gasUsed": 31853, + "gasUsed": 31831, } `; exports[`EthFoxVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68908, + "gasUsed": 68946, } `; exports[`EthFoxVault deposit deposit through receive fallback can be called by not blocked sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 76470, + "gasUsed": 76519, } `; exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for collateralized vault 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 113416, -} -`; - -exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for not collateralized vault 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 84597, + "gasUsed": 118081, } `; exports[`EthFoxVault ejecting user does not fail for user with no vault shares 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 55813, + "gasUsed": 55786, } `; exports[`EthFoxVault set blocklist manager admin can update blocklist manager 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 35963, + "gasUsed": 35941, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index aebac824..c1abab46 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,28 +10,28 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79671, + "gasUsed": 79638, } `; exports[`EthGenesisVault pulls assets on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 62296, + "gasUsed": 76981, } `; exports[`EthGenesisVault pulls assets on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 636076, + "gasUsed": 638161, } `; exports[`EthGenesisVault pulls assets on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 299702, + "gasUsed": 301759, } `; @@ -45,7 +45,7 @@ Object { exports[`EthGenesisVault update state splits penalty between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 100296, + "gasUsed": 119905, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index de6ccf5f..d605e28c 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,13 +3,48 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71069, + "gasUsed": 71137, } `; exports[`EthPrivErc20Vault deposit deposit through receive fallback can be called by whitelisted sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 78288, + "gasUsed": 78318, +} +`; + +exports[`EthPrivErc20Vault ejecting user does not fail for user with no osToken shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 98634, +} +`; + +exports[`EthPrivErc20Vault ejecting user does not fail for user with no vault shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 34188, +} +`; + +exports[`EthPrivErc20Vault ejecting user whitelister can eject all of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 98634, +} +`; + +exports[`EthPrivErc20Vault ejecting user whitelister can eject some of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 124911, +} +`; + +exports[`EthPrivErc20Vault transfer can transfer to whitelisted user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 59040, } `; diff --git a/test/__snapshots__/EthPrivVault.spec.ts.snap b/test/__snapshots__/EthPrivVault.spec.ts.snap new file mode 100644 index 00000000..0dde2ac6 --- /dev/null +++ b/test/__snapshots__/EthPrivVault.spec.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EthPrivVault ejecting user does not fail for user with no osToken shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 96619, +} +`; + +exports[`EthPrivVault ejecting user does not fail for user with no vault shares 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 33968, +} +`; + +exports[`EthPrivVault ejecting user whitelister can eject all of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 96619, +} +`; + +exports[`EthPrivVault ejecting user whitelister can eject some of the user assets 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 122896, +} +`; + +exports[`EthPrivVault mint osToken can mint from not whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 173886, +} +`; diff --git a/test/__snapshots__/EthVault.burn.spec.ts.snap b/test/__snapshots__/EthVault.burn.spec.ts.snap index f80e969a..59d844fa 100644 --- a/test/__snapshots__/EthVault.burn.spec.ts.snap +++ b/test/__snapshots__/EthVault.burn.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - burn burns osTokens 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 84120, + "gasUsed": 101220, } `; exports[`EthVault - burn updates position accumulated fee 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 84120, + "gasUsed": 101220, } `; diff --git a/test/__snapshots__/EthVault.deposit.spec.ts.snap b/test/__snapshots__/EthVault.deposit.spec.ts.snap index b687bcbf..fcc3d6d8 100644 --- a/test/__snapshots__/EthVault.deposit.spec.ts.snap +++ b/test/__snapshots__/EthVault.deposit.spec.ts.snap @@ -3,14 +3,14 @@ exports[`EthVault - deposit empty vault: no assets & no shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66733, + "gasUsed": 66711, } `; exports[`EthVault - deposit full vault: assets & shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66733, + "gasUsed": 66711, } `; @@ -24,6 +24,6 @@ Object { exports[`EthVault - deposit full vault: assets & shares update state and deposit 1`] = ` Object { "calldataByteLength": 260, - "gasUsed": 207274, + "gasUsed": 155335, } `; diff --git a/test/__snapshots__/EthVault.liquidate.spec.ts.snap b/test/__snapshots__/EthVault.liquidate.spec.ts.snap index 03013990..cbe7a222 100644 --- a/test/__snapshots__/EthVault.liquidate.spec.ts.snap +++ b/test/__snapshots__/EthVault.liquidate.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - liquidate calculates liquidation correctly 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 107267, + "gasUsed": 109382, } `; exports[`EthVault - liquidate can liquidate 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 107267, + "gasUsed": 109382, } `; diff --git a/test/__snapshots__/EthVault.mint.spec.ts.snap b/test/__snapshots__/EthVault.mint.spec.ts.snap index f146e4be..c3972025 100644 --- a/test/__snapshots__/EthVault.mint.spec.ts.snap +++ b/test/__snapshots__/EthVault.mint.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - mint mints osTokens to the receiver 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 171585, + "gasUsed": 171574, } `; exports[`EthVault - mint updates position accumulated fee 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 116697, + "gasUsed": 116686, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index e02c2d61..a70587f8 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 163912, + "gasUsed": 168267, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 137505, + "gasUsed": 109586, } `; diff --git a/test/__snapshots__/EthVault.redeem.spec.ts.snap b/test/__snapshots__/EthVault.redeem.spec.ts.snap index df8e05c3..5390f7e7 100644 --- a/test/__snapshots__/EthVault.redeem.spec.ts.snap +++ b/test/__snapshots__/EthVault.redeem.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - redeem osToken calculates redeem correctly 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 123428, + "gasUsed": 125543, } `; exports[`EthVault - redeem osToken can redeem 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 123428, + "gasUsed": 125543, } `; diff --git a/test/__snapshots__/EthVault.register.spec.ts.snap b/test/__snapshots__/EthVault.register.spec.ts.snap index 88b56b25..38f9e0da 100644 --- a/test/__snapshots__/EthVault.register.spec.ts.snap +++ b/test/__snapshots__/EthVault.register.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3332, - "gasUsed": 671554, + "gasUsed": 673647, } `; exports[`EthVault - register single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 322033, + "gasUsed": 324126, } `; diff --git a/test/__snapshots__/EthVault.settings.spec.ts.snap b/test/__snapshots__/EthVault.settings.spec.ts.snap index e7aaef84..076dfd07 100644 --- a/test/__snapshots__/EthVault.settings.spec.ts.snap +++ b/test/__snapshots__/EthVault.settings.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthVault - settings fee recipient can update 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 44036, + "gasUsed": 43992, } `; exports[`EthVault - settings keys manager can be updated by admin 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 53002, + "gasUsed": 52980, } `; exports[`EthVault - settings metadata IPFS hash only admin can update 1`] = ` Object { "calldataByteLength": 132, - "gasUsed": 32647, + "gasUsed": 32625, } `; diff --git a/test/__snapshots__/EthVault.state.spec.ts.snap b/test/__snapshots__/EthVault.state.spec.ts.snap index 06f3ed08..86f056d3 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -10,7 +10,14 @@ Object { exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 115144, + "gasUsed": 117653, +} +`; + +exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 107206, } `; diff --git a/test/__snapshots__/EthVault.token.spec.ts.snap b/test/__snapshots__/EthVault.token.spec.ts.snap index 88081c47..a0a89440 100644 --- a/test/__snapshots__/EthVault.token.spec.ts.snap +++ b/test/__snapshots__/EthVault.token.spec.ts.snap @@ -17,34 +17,34 @@ Object { exports[`EthVault - token permit accepts owner signature 1`] = ` Object { "calldataByteLength": 228, - "gasUsed": 82411, + "gasUsed": 82389, } `; exports[`EthVault - token transfer from when the spender has enough allowance when the token owner has enough balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 54802, + "gasUsed": 54827, } `; exports[`EthVault - token transfer from when the spender has unlimited allowance does not decrease the spender allowance 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 61278, + "gasUsed": 61303, } `; exports[`EthVault - token transfer when the sender transfers all balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 54487, + "gasUsed": 54490, } `; exports[`EthVault - token transfer when the sender transfers zero tokens transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 36563, + "gasUsed": 36566, } `; diff --git a/test/__snapshots__/EthVault.upgrade.spec.ts.snap b/test/__snapshots__/EthVault.upgrade.spec.ts.snap index 32051605..7750f50b 100644 --- a/test/__snapshots__/EthVault.upgrade.spec.ts.snap +++ b/test/__snapshots__/EthVault.upgrade.spec.ts.snap @@ -1,8 +1,50 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`EthVault - upgrade does not modify the state variables 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 82702, +} +`; + +exports[`EthVault - upgrade does not modify the state variables 2`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 83366, +} +`; + +exports[`EthVault - upgrade does not modify the state variables 3`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 82922, +} +`; + +exports[`EthVault - upgrade does not modify the state variables 4`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 83586, +} +`; + +exports[`EthVault - upgrade does not modify the state variables 5`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 82790, +} +`; + exports[`EthVault - upgrade works with valid call data 1`] = ` Object { "calldataByteLength": 132, - "gasUsed": 76096, + "gasUsed": 76084, +} +`; + +exports[`EthVault - upgrade works with valid call data 2`] = ` +Object { + "calldataByteLength": 132, + "gasUsed": 76084, } `; diff --git a/test/__snapshots__/EthVault.whitelist.spec.ts.snap b/test/__snapshots__/EthVault.whitelist.spec.ts.snap index 17849c51..0fff6a6c 100644 --- a/test/__snapshots__/EthVault.whitelist.spec.ts.snap +++ b/test/__snapshots__/EthVault.whitelist.spec.ts.snap @@ -3,14 +3,14 @@ exports[`EthVault - whitelist deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68944, + "gasUsed": 69044, } `; exports[`EthVault - whitelist deposit deposit through receive fallback can be called by whitelisted sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 76460, + "gasUsed": 76522, } `; @@ -24,13 +24,13 @@ Object { exports[`EthVault - whitelist whitelist can be updated by whitelister 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 53086, + "gasUsed": 53127, } `; exports[`EthVault - whitelist whitelist can be updated by whitelister 2`] = ` Object { "calldataByteLength": 68, - "gasUsed": 31174, + "gasUsed": 31215, } `; diff --git a/test/__snapshots__/EthVault.withdraw.spec.ts.snap b/test/__snapshots__/EthVault.withdraw.spec.ts.snap index baaed7fb..0c944164 100644 --- a/test/__snapshots__/EthVault.withdraw.spec.ts.snap +++ b/test/__snapshots__/EthVault.withdraw.spec.ts.snap @@ -3,44 +3,35 @@ exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 74983, + "gasUsed": 75784, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48012, + "gasUsed": 48640, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in single transaction 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 50422, + "gasUsed": 51208, } `; exports[`EthVault - withdraw claim exited assets for single user in single checkpoint 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48012, + "gasUsed": 48640, } `; -exports[`EthVault - withdraw enter exit queue locks shares for the time of exit 1`] = ` +exports[`EthVault - withdraw enter exit queue locks assets for the time of exit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 87054, -} -`; - -exports[`EthVault - withdraw get checkpoint index works with many checkpoints 1`] = `29876`; - -exports[`EthVault - withdraw redeem redeem transfers assets to receiver 1`] = ` -Object { - "calldataByteLength": 68, - "gasUsed": 58190, + "gasUsed": 77184, } `; diff --git a/test/__snapshots__/EthVaultFactory.spec.ts.snap b/test/__snapshots__/EthVaultFactory.spec.ts.snap index 339c4b4e..f0a7f936 100644 --- a/test/__snapshots__/EthVaultFactory.spec.ts.snap +++ b/test/__snapshots__/EthVaultFactory.spec.ts.snap @@ -3,55 +3,55 @@ exports[`EthVaultFactory EthErc20Vault private vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 602165, + "gasUsed": 577167, } `; exports[`EthVaultFactory EthErc20Vault private vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 453346, + "gasUsed": 428348, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 553968, + "gasUsed": 553235, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 405149, + "gasUsed": 404416, } `; exports[`EthVaultFactory EthVault private vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 528029, + "gasUsed": 503077, } `; exports[`EthVaultFactory EthVault private vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 379210, + "gasUsed": 354258, } `; exports[`EthVaultFactory EthVault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 479829, + "gasUsed": 479145, } `; exports[`EthVaultFactory EthVault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 331010, + "gasUsed": 330326, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index adbe7f1e..a47560d8 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -3,28 +3,28 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 677871, + "gasUsed": 679964, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 586277, + "gasUsed": 588370, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 328397, + "gasUsed": 330490, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1508, - "gasUsed": 274125, + "gasUsed": 276218, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index becc84c9..94be549f 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -3,34 +3,34 @@ exports[`RewardSplitter decrease shares owner can decrease shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 67101, + "gasUsed": 67079, } `; exports[`RewardSplitter increase shares owner can increase shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78767, + "gasUsed": 78745, } `; exports[`RewardSplitter sync rewards anyone can sync rewards 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 73126, + "gasUsed": 73104, } `; exports[`RewardSplitter withdraw rewards can claim vault tokens for ERC-20 vault 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78224, + "gasUsed": 78205, } `; exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 168565, + "gasUsed": 170678, } `; diff --git a/test/__snapshots__/VaultsRegistry.spec.ts.snap b/test/__snapshots__/VaultsRegistry.spec.ts.snap index 1c5ab981..da8cf135 100644 --- a/test/__snapshots__/VaultsRegistry.spec.ts.snap +++ b/test/__snapshots__/VaultsRegistry.spec.ts.snap @@ -3,7 +3,7 @@ exports[`VaultsRegistry factory can add vault 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 331010, + "gasUsed": 330326, } `; diff --git a/test/shared/artifacts/EthErc20Vault.json b/test/shared/artifacts/EthErc20Vault.json new file mode 100644 index 00000000..14d18a3a --- /dev/null +++ b/test/shared/artifacts/EthErc20Vault.json @@ -0,0 +1,1908 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EthErc20Vault", + "sourceName": "contracts/vaults/ethereum/EthErc20Vault.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_validatorsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenVaultController", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "sharedMevEscrow", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitingAssetsClaimDelay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "CapacityExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimTooEarly", + "type": "error" + }, + { + "inputs": [], + "name": "Collateralized", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeePercent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHealthFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLtv", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPosition", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecurityDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShares", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenMeta", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidators", + "type": "error" + }, + { + "inputs": [], + "name": "LowLtv", + "type": "error" + }, + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + }, + { + "inputs": [], + "name": "NotCollateralized", + "type": "error" + }, + { + "inputs": [], + "name": "NotHarvested", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "PermitInvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RedemptionExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeFailed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keysManager_", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6101a034620001b057601f6200566838819003918201601f19168301916001600160401b03831184841017620001b45780849260e094604052833981010312620001b0576200004e81620001c8565b6200005c60208301620001c8565b916200006b60408201620001c8565b926200007a60608301620001c8565b936200008960808401620001c8565b9160c06200009a60a08601620001c8565b9401519460805260a05260c0523060e052620000b5620001dd565b6101009346855261012093845260018060a01b03806101409216825261016092168252610180928352620000e8620001dd565b604051936153eb95866200027d8739608051868181611d5d015281816128b80152818161328c01528181613708015281816139a80152614716015260a0518661196b015260c0518681816142e10152614482015260e051868181611b590152613dfa01525185612bc801525184612e560152518381816104250152818161093e01528181610d0101528181611322015281816134040152613b2b015251828181610a1a01528181610dad015281816113ce0152613aaa015251818181612ba301526137500152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203620001b057565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460ff8160401c166200026a576001600160401b036002600160401b0319828216016200022b57505050565b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b60405163f92ee8a960e01b8152600490fdfe60806040526004361015610022575b3615610018575f80fd5b6100206133e5565b005b5f3560e01c806301e1d11414610397578063066055e01461039257806306fdde031461038d57806307a2d13a14610388578063095ea7b31461038357806318160ddd1461034c57806318f729501461037e5780631a7ff55314610379578063201b9eb51461037457806323b872dd1461036f5780632999ad3f1461036a5780632cdf740114610365578063313ce567146103605780633229fa951461035b57806333194c0a146103565780633644e515146103515780633a98ef391461034c578063439fab911461034757806343e82a7914610342578063469048401461033d5780634ec96b22146103385780634f1ef28614610333578063514e27081461032e57806352d1902d1461032957806353156f281461032457806354fd4d501461031f5780635c60da1b1461031a5780635cfc1a51146103155780635dddf3a81461031057806360d60e6e1461030b57806370a082311461029d57806372b410a81461030657806376b58b90146103015780637bde82f2146102fc5780637ecebe00146102f75780637fd6f15c146102f25780638697d2c2146102ed5780638ceab9aa146102e857806395d89b41146102e35780639b401cde146102de578063a1bf49aa146102d9578063a49a1e7d146102d4578063a9059cbb146102cf578063aaa4e836146102ca578063ac9650d8146102c5578063ad3cb1cc146102c0578063c6e6f592146102bb578063d505accf146102b6578063d83ad00c146102b1578063dd62ed3e146102ac578063e74b981b146102a7578063ef2a2158146102a2578063f04da65b1461029d578063f5e9de4d14610298578063f851a440146102935763f9609f080361000e57612a1b565b6129f3565b612860565b611cf7565b6127d8565b61279d565b612759565b61270e565b6124ed565b6124c4565b61247f565b61239b565b61229a565b61225c565b612205565b6121e7565b6121c9565b612125565b611fb2565b611f8d565b611f69565b611f2e565b611e10565b611dbf565b611d32565b611c57565b611c3d565b611c23565b611bef565b611bd4565b611bb0565b611b47565b611ad9565b611853565b61175e565b611736565b6112f7565b6111de565b61080e565b61117b565b611141565b611115565b6110fa565b6110e0565b610cd7565b610bfb565b6108ce565b61089b565b610842565b61076c565b610735565b61066f565b6103ca565b6103aa565b5f9103126103a657565b5f80fd5b346103a6575f3660031901126103a657602060cf5460801c604051908152f35b346103a65760203660031901126103a6576001600160801b03600435818116908181036103a657604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1928315610570575f9361053f575b50335f90815261016e6020526040902061046e90612a4b565b9361048085516001600160801b031690565b161561052d57836104c26104b56104a56104db946104a0610529996133ef565b61349f565b83516001600160801b0316612a84565b6001600160801b03168252565b335f90815261016e60205260409020612a9d565b612a9d565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b61056291935060203d602011610569575b61055a81836105f4565b810190612a31565b915f610455565b503d610550565b612a40565b90600182811c921680156105a3575b602083101461058f57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610584565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176105dc57604052565b6105ad565b6001600160401b0381116105dc57604052565b90601f801991011681019081106001600160401b038211176105dc57604052565b5f5b8381106106265750505f910152565b8181015183820152602001610617565b9060209161064f81518092818552858086019101610615565b601f01601f1916010190565b90602061066c928181520190610636565b90565b346103a6575f3660031901126103a6576040515f805461068e81610575565b8084529060209060019081811690811561070b57506001146106c7575b610529856106bb818703826105f4565b6040519182918261065b565b5f80805293505f805160206153168339815191525b8385106106f8575050505081016020016106bb826105296106ab565b80548686018401529382019381016106dc565b869550610529969350602092506106bb94915060ff191682840152151560051b82010192936106ab565b346103a65760203660031901126103a6576020610753600435612ac6565b604051908152f35b6001600160a01b038116036103a657565b346103a65760403660031901126103a6576004356107898161075b565b6001600160a01b038116906024359082156107fc576107c48291335f52600260205260405f209060018060a01b03165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60405163d92e233d60e01b8152600490fd5b346103a6575f3660031901126103a65760206001600160801b0360cf5416604051908152f35b908160809103126103a65790565b60603660031901126103a65760043561085a8161075b565b6024356108668161075b565b604435906001600160401b0382116103a65760209261089461088f610753943690600401610834565b612aec565b349061464f565b346103a65760203660031901126103a6576004356001600160401b0381116103a65761088f610020913690600401610834565b346103a65760603660031901126103a65760048035906108ed8261075b565b60243590604435926108fe8461075b565b61090661396c565b61090e61398d565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af1978815610570575f98610bdc575b50335f90815261016e60205260409020839061099790612a4b565b946001600160801b036109b187516001600160801b031690565b1615610b7a576109c0866133ef565b6109ec6109df6109cf8961349f565b88516001600160801b0316612b40565b6001600160801b03168752565b335f90815260d3602052604090208490610a07905b54612ac6565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa91821561057057610a96928592610a5a925f92610b5b575b506134f5565b92610a6c87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa928315610570575f93610b3c575b505010610b2e5750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e5891610af5610529976104d63360018060a01b03165f5261016e60205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610b53929350803d106105695761055a81836105f4565b905f80610aa8565b610b73919250843d86116105695761055a81836105f4565b905f610a54565b885163752a536d60e01b8152915083828681865afa801561057057610bab610bba9187945f91610bbf575b5061349f565b6001600160801b031687860152565b6109c0565b610bd69150873d89116105695761055a81836105f4565b5f610ba5565b610bf4919850823d84116105695761055a81836105f4565b965f61097c565b346103a65760603660031901126103a657600435610c188161075b565b60243590610c258261075b565b6001600160a01b0381165f8181526002602090815260408083203384529091529020546044359160018201610c75575b610c6984610c6485888361476a565b613a18565b60405160018152602090f35b919093818503948511610ca9575f928352600260209081526040808520338652909152909220939093559180610c69610c55565b612a70565b60609060031901126103a65760043590602435610cca8161075b565b9060443561066c8161075b565b346103a657610ce536610cae565b906001600160a01b03808316156107fc57610cfe61398d565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103a65760408051631d8557d760e01b815260049491905f81878183875af18015610570576110c7575b506001600160a01b0383165f90815261016e60205260409020610d7190612a4b565b6001600160801b03610d8a82516001600160801b031690565b16156110b757610d99816133ef565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa96871561057057610e08975f955f9161107e575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa801561057057610e23925f9161106157506134f5565b95610e41610a018960018060a01b03165f5260d360205260405f2090565b918288118015611051575b61104157908a610e8992610e6788516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa90811561057057670de0b6b3a764000093610ec5938d5f94611018575b5050610eb9610ebf91613248565b92613265565b9161356f565b101561100a578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af1908115610570577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610fe795610f5f93610fec575b5050610f426104b56104a58c61349f565b6001600160a01b0386165f90815261016e60205260409020612a9d565b610f68826140b7565b90610fa6610f8b610f788561349f565b60cf5460801c036001600160801b031690565b6001600160801b0360cf549181199060801b1691161760cf55565b610fb08286614dfc565b610fba8389614009565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b8161100292903d106105695761055a81836105f4565b505f80610f31565b835163185cfc6d60e11b8152fd5b610ebf929450610eb9918161103892903d106105695761055a81836105f4565b9391508d610eab565b865163efda1a2760e01b81528490fd5b5061105a612b5b565b8811610e4c565b61107891508c8d3d106105695761055a81836105f4565b5f610a54565b90506110a391955060a03d60a0116110b0575b61109b81836105f4565b810190613bb1565b509692509050945f610de4565b503d611091565b815163673f032f60e11b81528690fd5b806110d46110da926105e1565b8061039c565b5f610d4f565b346103a6575f3660031901126103a6576020610753612b5b565b346103a6575f3660031901126103a657602060405160128152f35b346103a6575f3660031901126103a657602061112f612b8a565b6040516001600160a01b039091168152f35b346103a6575f3660031901126103a65760206040517f9480c4a5d7e604111fbc986cd90c895a458ca155fe13c10879b93c4592ce29fd8152f35b346103a6575f3660031901126103a6576020610753612bc5565b9060206003198301126103a6576004356001600160401b03928382116103a657806023830112156103a65781600401359384116103a657602484830101116103a6576024019190565b6111e736611195565b905f8051602061539683398151915254916001600160401b0360ff8460401c16159316801590816112ef575b60011490816112e5575b1590816112dc575b506112ca575f80516020615396833981519152805467ffffffffffffffff1916600117905561125891836112a657612c39565b61125e57005b5f80516020615396833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020615396833981519152805460ff60401b1916600160401b179055612c39565b60405163f92ee8a960e01b8152600490fd5b9050155f611225565b303b15915061121d565b849150611213565b346103a65761130536610cae565b906001600160a01b0390818316156107fc5761131f61398d565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103a65760408051631d8557d760e01b815260049291905f81858183875af1801561057057611723575b506001600160a01b0384165f90815261016e6020526040902061139190612a4b565b926001600160801b036113ab85516001600160801b031690565b1615611715576113ba846133ef565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa938415610570575f955f956116e7575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa988915610570575f996116c8575b506001600160a01b038a165f90815260d36020526040902061145990610a01565b90818a1180156116b8575b6116a85761149f908661147e87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa918215610570575f92611687575b506114bd91926134f5565b11611677578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af191821561057057859261165a575b506115068d61349f565b84516001600160801b03169061151b91612a84565b6001600160801b031684526001600160a01b038a165f90815261016e602052604090208461154891612a9d565b611551896140b7565b9761155b8a61349f565b60cf5460801c036001600160801b031661158a906001600160801b0360cf549181199060801b1691161760cf55565b611594898c614dfc565b6001600160a01b038b165f90815260d360205260409020546115b590612ac6565b906115bf916134f5565b935187519182526001600160801b0316868201908152909283918290036020019082905afa928315610570575f9361163b575b50501161162d575091610fe7917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610fba8389614009565b9051631d8fa13d60e31b8152fd5b611652929350803d106105695761055a81836105f4565b905f806115f2565b61167090833d85116105695761055a81836105f4565b505f6114fc565b855163324b20e160e11b81528590fd5b6114bd92506116a290883d8a116105695761055a81836105f4565b916114b2565b875163efda1a2760e01b81528790fd5b506116c1612b5b565b8a11611464565b6116e0919950853d87116105695761055a81836105f4565b975f611438565b61142592965061170791955060a03d60a0116110b05761109b81836105f4565b505050959095949091611401565b905163673f032f60e11b8152fd5b806110d4611730926105e1565b5f61136f565b346103a6575f3660031901126103a657609c546040516001600160a01b039091168152602090f35b346103a65760203660031901126103a65760043561177b8161075b565b60018060a01b03165f5261016e602052602060405f206040519061179e826105c1565b54906001600160801b03918281169081835260801c848301526117c6575b5116604051908152f35b6117cf816133ef565b6117bc565b6040519060a082018281106001600160401b038211176105dc57604052565b60405190611800826105c1565b565b6001600160401b0381116105dc57601f01601f191660200190565b92919261182982611802565b9161183760405193846105f4565b8294818452818301116103a6578281602093845f960137010152565b6040806003193601126103a657600490813561186e8161075b565b6024356001600160401b0381116103a657366023820112156103a65761189d903690602481870135910161181d565b916118a6613df0565b8051926118dd846118cf60209363439fab9160e01b858401528460248401526044830190610636565b03601f1981018652856105f4565b6118e5613df0565b6118ed6140a3565b6001600160a01b03838116801592919087908415611aa4575b8415611a36575b84156119d2575b5050821561193c575b505061192d576100208383614a39565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa918215610570575f926119a5575b5050155f8061191d565b6119c49250803d106119cb575b6119bc81836105f4565b810190612daf565b5f8061199b565b503d6119b2565b855163054fd4d560e41b81529294508391839182905afa9081156105705760029160ff915f91611a09575b5016141591865f611914565b611a299150843d8611611a2f575b611a2181836105f4565b810190614a24565b5f6119fd565b503d611a17565b935050835163198ca60560e11b815282818981875afa9081156105705788917f9480c4a5d7e604111fbc986cd90c895a458ca155fe13c10879b93c4592ce29fd915f91611a87575b5014159361190d565b611a9e9150853d87116105695761055a81836105f4565b5f611a7e565b5f80516020615336833981519152549094508490611ad2906001600160a01b03165b6001600160a01b031690565b1493611906565b346103a65760203660031901126103a6576004356001600160a01b03611afd612d84565b163303611b355780610107555f61010855337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346103a6575f3660031901126103a6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611b9e5760206040515f805160206153368339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126103a6576001600160a01b03611bcb612b8a565b163303611b3557005b346103a6575f3660031901126103a657602060405160018152f35b346103a6575f3660031901126103a6575f80516020615336833981519152546040516001600160a01b039091168152602090f35b346103a6575f3660031901126103a6576020610753612d76565b346103a6575f3660031901126103a657602061112f612d84565b346103a65760203660031901126103a65760d180549081905f6004355b848210611ca557505050811015611c9a57610529905b6040519081529081906020820190565b506105295f19611c8a565b909193808316906001818518811c8301809311610ca9575f8790525f805160206153768339815191528301546001600160a01b0316841015611cec575050935b9190611c74565b909591019250611ce5565b346103a65760203660031901126103a657600435611d148161075b565b60018060a01b03165f5260d3602052602060405f2054604051908152f35b346103a6575f3660031901126103a657604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610570576020915f91611da2575b506040519015158152f35b611db99150823d84116119cb576119bc81836105f4565b5f611d97565b346103a65760803660031901126103a657610529611df3600435611de28161075b565b606435906044359060243590612dd1565b604080519384526020840192909252908201529081906060820190565b346103a6576040806003193601126103a65760043560243591611e328361075b565b611e3a61522f565b8115611f1e576001600160a01b0383168015611f0d57611e5983612ac6565b928315611efc57611e68612b5b565b8411611eeb57611e9f8461052996611e90610f8b611e858461349f565b60cf5460801c612a84565b611e9a8433614dfc565b614009565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea8348090604090a3611edd33613a18565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346103a65760203660031901126103a657600435611f4b8161075b565b60018060a01b03165f526003602052602060405f2054604051908152f35b346103a6575f3660031901126103a657602061ffff609c5460a01c16604051908152f35b346103a65760603660031901126103a657610529611df3604435602435600435612e4b565b346103a6576040806003193601126103a6576004359060243590611fd58261075b565b611fdd61396c565b8215611f1e576001600160a01b038216928315611f0d57610529936120be6120a28361202061201460d0546001600160801b031690565b6001600160801b031690565b816120806120358361203061524f565b612e3e565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a61206f81608081015b03601f1981018352826105f4565b5190205f5260d260205260405f2090565b55335f90815260d36020526040902061209a838254612dc4565b90550161349f565b6001600160801b03166001600160801b031960d054161760d055565b82518481526020810183905233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f90604090a36120fb33613a18565b8151908152309033905f8051602061535683398151915290602090a3519081529081906020820190565b346103a6575f3660031901126103a6576040515f6001805461214681610575565b808552916020916001811690811561070b575060011461217057610529856106bb818703826105f4565b60015f90815293507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8385106121b6575050505081016020016106bb826105296106ab565b805486860184015293820193810161219a565b346103a6575f3660031901126103a657602061010754604051908152f35b346103a6575f3660031901126103a657602061010854604051908152f35b346103a6576122577f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf61223736611195565b92906122416140a3565b6040519182916020835233956020840191612fdf565b0390a2005b346103a65760403660031901126103a65761228660043561227c8161075b565b602435903361476a565b61228f33613a18565b602060405160018152f35b346103a65760203660031901126103a6576004356122b78161075b565b6122bf6140a3565b6001600160a01b031680156107fc5761010980546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156103a6578235916001600160401b0383116103a6576020808501948460051b0101116103a657565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b84831061236d5750505050505090565b909192939495848061238b600193603f198682030187528a51610636565b980193019301919493929061235d565b346103a65760203660031901126103a657600480356001600160401b0381116103a6576123cc903690600401612308565b916123d683613016565b925f5b8181106123ee57604051806105298782612338565b5f806123fb8385886130a5565b6040939161240d8551809381936130c5565b0390305af49061241b6130d2565b9115612442575090600191612430828861316c565b5261243b818761316c565b50016123d9565b848260448151106103a657612466818361247b930151602480918301019101613101565b925162461bcd60e51b8152928392830161065b565b0390fd5b346103a6575f3660031901126103a65761052960405161249e816105c1565b60058152640352e302e360dc1b6020820152604051918291602083526020830190610636565b346103a65760203660031901126103a65760206107536004356140b7565b60ff8116036103a657565b346103a65760e03660031901126103a65760043561250a8161075b565b6024356125168161075b565b60443590606435926084359061252b826124e2565b6001600160a01b038381169590929086156107fc574281106126fc576020915f9161261e61262a89878a6125e1612560612bc5565b6001600160a01b0384165f9081526003602052604090209097908054906001820190556040519586948d8601968791959493909260a09360c08401977f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98552600180871b038092166020860152166040840152606083015260808201520152565b03916125f5601f19938481018352826105f4565b5190206040519384918983019687909160429261190160f01b8352600283015260228201520190565b039081018352826105f4565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa15610570575f519282841680159081156126ef575b506126dd576126ca85916126b57f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259660018060a01b03165f52600260205260405f2090565b9060018060a01b03165f5260205260405f2090565b5560405193845216918060208101610fe7565b6040516323389ba560e21b8152600490fd5b905083831614155f612670565b604051631ab7da6b60e01b8152600490fd5b346103a6575f3660031901126103a65760206001600160801b0360d05416604051908152f35b60409060031901126103a65760043561274c8161075b565b9060243561066c8161075b565b346103a657602061279461276c36612734565b6001600160a01b039182165f9081526002855260408082209290931681526020919091522090565b54604051908152f35b346103a65760203660031901126103a6576100206004356127bd8161075b565b6127c56140a3565b614146565b908160a09103126103a65790565b346103a65760803660031901126103a6576001600160401b036004358181116103a6576128099036906004016127ca565b6024358281116103a657612821903690600401612308565b6044929192358481116103a65761283c903690600401612308565b916064359586116103a657612858610020963690600401612308565b95909461327c565b346103a6576040806003193601126103a6576004906001600160401b0382358181116103a65761289390369085016127ca565b906024359081116103a6576128ab9036908501612308565b9390926128b661398d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156103a6575f8251809263837d444160e01b82528183816129058a8a83016131b1565b03925af18015610570576129e0575b506801bc16d674ec800000612927612b5b565b106129d3578083019360b061293c8686613073565b9050036129c557612990612994916101085497610107549061298361297b8b6129658c8c613073565b6120618b949294519384926020840196876133b1565b5190206133ce565b602081519101209261443c565b1590565b6129b8576100206001866129b16129ab8888613073565b90614474565b0161010855565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b806110d46129ed926105e1565b5f612914565b346103a6575f3660031901126103a6576037546040516001600160a01b039091168152602090f35b6020610753612a2936612734565b90349061464f565b908160209103126103a6575190565b6040513d5f823e3d90fd5b90604051612a58816105c1565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211610ca957565b815160209092015160801b6001600160801b0319166001600160801b0392909216919091179055565b60cf546001600160801b0381169081612ade57505090565b9161066c9260801c9061356f565b612af5906136d7565b9080612b31575b50612b0357565b612b0b614cff565b80612b14575b50565b5f906040519081525f8051602061535683398151915260203092a3565b612b3a9061386d565b5f612afc565b9190916001600160801b0380809416911601918211610ca957565b4760d054612b716001600160801b038216612ac6565b9060801c01908181115f14612b84570390565b50505f90565b6101a1546001600160a01b03168015612ba05790565b507f000000000000000000000000000000000000000000000000000000000000000090565b467f000000000000000000000000000000000000000000000000000000000000000003612bf25760045490565b61066c613bd8565b908160209103126103a6575161066c8161075b565b359061ffff821682036103a657565b9080601f830112156103a65781602061066c9335910161181d565b60405163e7f6f22560e01b815290916020918281600481335afa908115610570575f91612d59575b50604051636f4fa30f60e01b8152918383600481335afa928315610570575f93612d2a575b50840183858203126103a65784356001600160401b03958682116103a657019060a0828203126103a657612cb86117d4565b9482358652612cc8818401612c0f565b9086015260408201358681116103a65781612ce4918401612c1e565b604086015260608201358681116103a65781612d01918401612c1e565b606086015260808201359586116103a65761180095612d209201612c1e565b6080840152613cfe565b612d4b919350843d8611612d52575b612d4381836105f4565b810190612bfa565b915f612c86565b503d612d39565b612d709150833d8511612d5257612d4381836105f4565b5f612c61565b60d4548061066c57505f1990565b610109546001600160a01b0390811680612da057506037541690565b905090565b801515036103a657565b908160209103126103a6575161066c81612da5565b91908203918211610ca957565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612e21929091612e0a8160808101612061565b5190205f5260d260205260405f2054928391613e6e565b9091828103908111610ca95792565b9060018201809211610ca957565b91908201809211610ca957565b929190915f93612e7b7f000000000000000000000000000000000000000000000000000000000000000085612e3e565b4210612fb55760408051336020820190815291810186905260608082018490528152601f1991612ebc91612eb06080826105f4565b51902094868433612dd1565b9096909587878115612fa75750505f90815260d2602052604081205560018211612f60575b505050612f19612efe612ef38561349f565b60d05460801c612a84565b6001600160801b0360d0549181199060801b1691161760d055565b612f238333614009565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b612f9e91929750612f718785612e3e565b6040805133602082019081529181019390935260608301829052909890919061206f90826080810161261e565b555f8080612ee1565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116105dc5760051b60200190565b9061302082612fff565b61302d60405191826105f4565b828152809261303e601f1991612fff565b01905f5b82811061304e57505050565b806060602080938501015201613042565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156103a657018035906001600160401b0382116103a6576020019181360383136103a657565b908210156130c0576130bc9160051b810190613073565b9091565b61305f565b908092918237015f815290565b3d156130fc573d906130e382611802565b916130f160405193846105f4565b82523d5f602084013e565b606090565b6020818303126103a6578051906001600160401b0382116103a6570181601f820112156103a657805161313381611802565b9261314160405194856105f4565b818452602082840101116103a65761066c9160208085019101610615565b8051156130c05760200190565b80518210156130c05760209160051b010190565b9035601e19823603018112156103a65701602081359101916001600160401b0382116103a65781360383136103a657565b9060a061066c926020815282356020820152602083013560408201526131ed6131dd6040850185613180565b84606085015260c0840191612fdf565b906132206132156132016060870187613180565b601f19858703810160808701529591612fdf565b946080810190613180565b93909282860301910152612fdf565b906801bc16d674ec8000009180830292830403610ca957565b90670de0b6b3a764000091828102928184041490151715610ca957565b9061271091828102928184041490151715610ca957565b92909493919561328a61398d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156103a6576040965f8851809263837d444160e01b82528183816132de8c600483016131b1565b03925af180156105705761339e575b506132f6612b5b565b6132ff8961322f565b1161338d5787158015613373575b613362579161333e95939161333889612990979561333261010754978c810190613073565b906142b6565b9461442a565b613352575061180090610108540161010855565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061338087860186613073565b905060b08902141561330d565b86516396d8043360e01b8152600490fd5b806110d46133ab926105e1565b5f6132ed565b9392916020916133c991604087526040870191612fdf565b930152565b9060405191602083015260208252611800826105c1565b612b113433614587565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f91613480575b5060208201916001600160801b03918284511691828214613479578361346c6104a061347495858486511661356f565b16905261349f565b169052565b5050505050565b613499915060203d6020116105695761055a81836105f4565b5f61343c565b6001600160801b03908181116134b3571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156134f0570490565b6134d2565b90808202905f1981840990828083109203918083039214613564576127109082821115613552577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146135e2578483111561355257829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061066c92506134e6565b908160609103126103a6578051916040602083015192015161066c81612da5565b81835290916001600160fb1b0383116103a65760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036103a657604083015260408101356136638161075b565b6001600160a01b031660608381019190915281013536829003601e19018112156103a65701602081359101906001600160401b0381116103a6578060051b360382136103a65760a08360808061066c9601520191613610565b9190915f8382019384129112908015821691151617610ca957565b6040516325f56f1160e01b81526001600160a01b039291606090829081906137029060048301613634565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af1928315610570575f915f905f95613828575b5084156137d5578161374c612b8a565b16917f00000000000000000000000000000000000000000000000000000000000000001682146137ce57509060205f92600460405180958193634641257d60e01b83525af1908115610570576137a9925f926137ad575b506136bc565b9190565b6137c791925060203d6020116105695761055a81836105f4565b905f6137a3565b90816137db575b50509190565b803b156103a657604051636ee3193160e11b815260048101929092525f908290602490829084905af1801561057057613815575b806137d5565b806110d4613822926105e1565b5f61380f565b9194505061384e915060603d606011613856575b61384681836105f4565b8101906135ef565b93905f61373c565b503d61383c565b600160ff1b8114610ca9575f0390565b61387c61201460cf5460801c90565b5f8212613953578161388d91612e3e565b9061389a610f8b8361349f565b6138af609c549161ffff8360a01c16906134f5565b801561394e57807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc35318686547936138ed61201460cf546001600160801b031690565b8061393857505061393390925b6001600160a01b03169161390e8484614c97565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613933926139489203908461356f565b926138fa565b505050565b6104a0610f8b916139666118009461385d565b90612dc4565b6139746146fb565b1561397b57565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f916139f9575b506139e757565b60405163e775715160e01b8152600490fd5b613a12915060203d6020116119cb576119bc81836105f4565b5f6139e0565b6001600160a01b0381165f90815261016e60205260409020613a3990612a4b565b906001600160801b03613a5383516001600160801b031690565b1615613bad57610a01613a8a91613a6861398d565b613a71846133ef565b6001600160a01b03165f90815260d36020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa91821561057057613aed8693613afb92613b27965f92613b9557506134f5565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa928315610570575f93613b76575b505010613b6457565b604051633684c65960e01b8152600490fd5b613b8d929350803d106105695761055a81836105f4565b905f80613b5b565b610b73919250863d88116105695761055a81836105f4565b5050565b908160a09103126103a6578051916020820151916040810151916080606083015192015190565b6040515f905f5490613be982610575565b9283825260209384830193600190866001821691825f14613cde575050600114613c9b575b50509181613c24613c95936120619503826105f4565b519020604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f95810195865260208601929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69085015246606085015230608085015291829060a0850190565b51902090565b5f80805286935091905f805160206153168339815191525b828410613cc95750505082010181613c24613c0e565b80548685018601528794909301928101613cb3565b60ff1916875292151560051b85019092019250839150613c249050613c0e565b919091613d096147e6565b6080820151613d166147e6565b603780546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190613d65908261065b565b0390a2602082015192613d766147e6565b61271061ffff851611613dde57613dd693613d93613dc693614146565b609c549061ffff60a01b9060a01b169061ffff60a01b191617609c55613db98351614814565b613dc1614844565b614865565b6060604082015191015190614894565b6118006149c1565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613e2e575b5050611b9e57565b5f805160206153368339815191525416141590505f80613e26565b90604051613e56816105c1565b91546001600160a01b038116835260a01c6020830152565b60d1545f948594939091808410801590614001575b613ff45783613fbe575f5b60d15f526001600160a01b0316613eb35f805160206153768339815191528601613e49565b8051909790613eca906001600160a01b0316611ac6565b98613eef613ee36020809b01516001600160601b031690565b6001600160601b031690565b948381108015613fb4575b613fa25791600193979a95613f19613f25939488035b838c0390614ae4565b8092019887039161356f565b01970193808611801590613f98575b613f8d5760d15f528290613f565f805160206153768339815191528701613e49565b805190890151969992966001600160a01b039091169460019392613f259290916001600160601b0390911690613f19908803613f10565b945050509250509190565b5081851015613f34565b60405163e8722f8f60e01b8152600490fd5b50808b1115613efa565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce28401546001600160a01b0316613e8e565b505093505050505f905f90565b508415613e83565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f009160028354146140915760028355814710614079575f918291829182916001600160a01b03165af161405b6130d2565b50156140675760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b6037546001600160a01b03163303611b3557565b60cf54906001600160801b038216811580156140e6575b156140d95750905090565b61066c9260801c9161356f565b5080156140ce565b60cf546001600160801b038116908215801561413e575b1561410f57505090565b60801c9061411e82828561356f565b9282156134f0570961412d5790565b600181018091111561066c57612a70565b508115614105565b61414e61398d565b6001600160a01b0316801561419657609c80546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b906141b282612fff565b6141bf60405191826105f4565b82815280926141d0601f1991612fff565b0190602036910137565b906030116103a65790603090565b906090116103a65760300190606090565b9060b0116103a65760900190602090565b909392938483116103a65784116103a6578101920390565b90156130c05790565b91908110156130c05760051b0190565b359060208110614249575090565b5f199060200360031b1b1690565b969594906133c993614278614286926060979560808c5260808c0191612fdf565b9089820360208b0152610636565b918783036040890152612fdf565b90602061066c928181520190612fc7565b91602061066c938181520191612fdf565b9193929061010854925f925f906142cc816141a8565b976142d5614af1565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106143165750505050505050505050565b60b061432691018099898561420a565b9960409a8d6143628d5161434a6020918281019061297b816120618c8a8d876133b1565b80519101209161435b858b8b61422b565b359061316c565b5261436d81846141da565b909361438d61438761437f85846141e8565b9590936141f9565b9061423b565b908a3b156103a6578b8f5f936143b8915196879485946304512a2360e31b8652888c60048801614257565b03816801bc16d674ec8000008d5af19384156105705761440b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298614417575b5097019e51928392836142a5565b0390a101989097614303565b806110d4614424926105e1565b5f6143fd565b906144389495939291614b32565b1490565b9192915f915b808310614450575050501490565b90919261446b60019161446486858761422b565b35906150b1565b93019190614442565b816030116103a657614387917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166144b2614af1565b906144c96144c084866141e8565b969094866141f9565b94813b156103a6576801bc16d674ec8000005f9461452f97604051988996879586946304512a2360e31b86526080600487015261452061450d8d6084890190612fc7565b60031994858983030160248a0152610636565b92868403016044870152612fdf565b90606483015203925af1908115610570577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261393392614578575b5060405191829182614294565b614581906105e1565b5f61456b565b919061459161398d565b6001600160a01b0383169081156107fc57801561463d57806145b861201460cf5460801c90565b01936145c2612d76565b851161462b57610f8b946145e9916145e46145dc856140ee565b97889361349f565b614c97565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b9092919261465b61398d565b6001600160a01b0382169182156107fc57811561463d578161468261201460cf5460801c90565b0161468b612d76565b811161462b57610f8b956146d2614626927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c946145e46146ca886140ee565b9a8b9361349f565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f91614751575090565b61066c915060203d6020116119cb576119bc81836105f4565b6001600160a01b039081169190821580156147dc575b6107fc57825f5260d360205260405f2090815492858403938411610ca9575f8051602061535683398151915293602093556147cb8160018060a01b03165f5260d360205260405f2090565b8681540190556040519586521693a3565b5080821615614780565b60ff5f805160206153968339815191525460401c161561480257565b604051631afcd79f60e31b8152600490fd5b61481c6147e6565b8015614832576001810161482d5750565b60d455565b6040516331278a8760e01b8152600490fd5b61484c6147e6565b6801bc16d674ec80000061485e612d76565b1061483257565b61486d6147e6565b6001600160a01b03168061487e5750565b6101a180546001600160a01b0319169091179055565b61489c6147e6565b601e81511180156149b6575b6149a4576148b46147e6565b8051906001600160401b0382116105dc576148d8826148d35f54610575565b614e67565b602090816001601f8511146149305750918061490e9261491595945f92614925575b50508160011b915f199060031b1c19161790565b5f55614f31565b611800614920613bd8565b600455565b015190505f806148fa565b5f80529190601f1984165f80516020615316833981519152935f905b82821061498c57505091600193918561491597969410614974575b505050811b015f55614f31565b01515f1960f88460031b161c191690555f8080614967565b8060018697829497870151815501960194019061494c565b604051632d3f993760e21b8152600490fd5b50600a8251116148a8565b6149c96147e6565b6149d16147e6565b6149d96147e6565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca003410614a1257612b113430614587565b60405163ea2559bb60e01b8152600490fd5b908160209103126103a6575161066c816124e2565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614ac3575b50614a8957604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206153368339815191528403614aaa5761180092935061500f565b604051632a87526960e21b815260048101859052602490fd5b614add91955060203d6020116105695761055a81836105f4565b935f614a63565b9080821015612da0575090565b604051600160f81b60208201525f60218201523060601b602c8201526020815261066c816105c1565b5f198114610ca95760010190565b3561066c81612da5565b9293919091805193614b448486612e3e565b614b4d87612e30565b03614b8f57614b5b866141a8565b945f8094885f965f5b828110614bc7575050159150614ba190505750505003614b8f57614b8b915f19019061316c565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614bb9575050614b8b9061315f565b614bc39250614222565b3590565b8a86861015614c7a5750614bf9614bf482614beb614be489614b1a565b988c61316c565b51955b8761422b565b614b28565b15614c5f578a86861015614c3e5750614c2a60019293614c22614c1b88614b1a565b978b61316c565b515b906150b1565b614c34828d61316c565b5201908a91614b64565b92614c2a90614c5984614c5360019691614b1a565b9661316c565b51614c24565b614c2a60019293614464614c728c614b1a565b9b8d8b61422b565b91614bf482614c9083614c53614bf99591614b1a565b5195614bee565b5f8051602061535683398151915260205f92614cb28561349f565b60cf5490614cca6001600160801b0391828416612b40565b6001600160801b031990921691161760cf556001600160a01b031680845260d3825260408085208054870190555194855293a3565b60d054906001600160801b038216918215614df65760801c614d33614d248247612dc4565b614d2d85612ac6565b90614ae4565b908115614def57614d43826140b7565b938415614de75782614d6f612efe6104a061180096610f8b966120306120a26104a08d611e859a612dc4565b614d79818761512b565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16104a0614dcb614dba8861349f565b60cf546001600160801b0316612a84565b6001600160801b03166001600160801b031960cf54161760cf55565b505f93505050565b505f925050565b505f9150565b6001600160a01b03165f81815260d360205260409020805483810391908211610ca9575f935f805160206153568339815191529260209255614e3d8161349f565b60cf54906001600160801b03908183160316906001600160801b0319161760cf55604051908152a3565b601f8111614e73575050565b5f80525f80516020615316833981519152906020601f840160051c83019310614eb6575b601f0160051c01905b818110614eab575050565b5f8155600101614ea0565b9091508190614e97565b90601f8211614ecd575050565b60019160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906020601f840160051c83019310614f27575b601f0160051c01905b818110614f1d57505050565b5f81558201614f11565b9091508190614f08565b9081516001600160401b0381116105dc57600190614f5881614f538454610575565b614ec0565b602080601f8311600114614f8d57508190614f899394955f926149255750508160011b915f199060031b1c19161790565b9055565b90601f19831695614fbf60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690565b925f905b888210614ff85750508385969710614fe0575b505050811b019055565b01515f1960f88460031b161c191690555f8080614fd6565b808785968294968601518155019501930190614fc3565b90813b15615090575f8051602061533683398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561507557612b1191615212565b50503461507e57565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b818110156150c5575f5260205260405f2090565b905f5260205260405f2090565b60d15490600160401b8210156105dc57600182018060d1558210156130c05760d15f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f8051602061537683398151915290910155565b908115801561520a575b6151f85760d154806151c257505f905b6001600160a01b03918216928301928310610ca9578183116151a257611800929161518d61517561519d93615291565b9161517e6117f3565b94166001600160a01b03168452565b6001600160601b03166020830152565b6150d2565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b031690615145565b604051632ec8835b60e21b8152600490fd5b508015615135565b5f8061066c93602081519101845af46152296130d2565b916152c4565b6152376146fb565b61523d57565b6040516389a1dc6360e01b8152600490fd5b60d1548061525c57505f90565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b0316611ac6565b6001600160601b03908181116152a5571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b906152d9575080511561406757805190602001fd5b8151158061530c575b6152ea575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156152e256fe290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce3f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212201b7a2a4606a5e03acc6b226b34e17aaa62090ae9ec2eb74766012a9b7091a63064736f6c63430008160033", + "deployedBytecode": "0x60806040526004361015610022575b3615610018575f80fd5b6100206133e5565b005b5f3560e01c806301e1d11414610397578063066055e01461039257806306fdde031461038d57806307a2d13a14610388578063095ea7b31461038357806318160ddd1461034c57806318f729501461037e5780631a7ff55314610379578063201b9eb51461037457806323b872dd1461036f5780632999ad3f1461036a5780632cdf740114610365578063313ce567146103605780633229fa951461035b57806333194c0a146103565780633644e515146103515780633a98ef391461034c578063439fab911461034757806343e82a7914610342578063469048401461033d5780634ec96b22146103385780634f1ef28614610333578063514e27081461032e57806352d1902d1461032957806353156f281461032457806354fd4d501461031f5780635c60da1b1461031a5780635cfc1a51146103155780635dddf3a81461031057806360d60e6e1461030b57806370a082311461029d57806372b410a81461030657806376b58b90146103015780637bde82f2146102fc5780637ecebe00146102f75780637fd6f15c146102f25780638697d2c2146102ed5780638ceab9aa146102e857806395d89b41146102e35780639b401cde146102de578063a1bf49aa146102d9578063a49a1e7d146102d4578063a9059cbb146102cf578063aaa4e836146102ca578063ac9650d8146102c5578063ad3cb1cc146102c0578063c6e6f592146102bb578063d505accf146102b6578063d83ad00c146102b1578063dd62ed3e146102ac578063e74b981b146102a7578063ef2a2158146102a2578063f04da65b1461029d578063f5e9de4d14610298578063f851a440146102935763f9609f080361000e57612a1b565b6129f3565b612860565b611cf7565b6127d8565b61279d565b612759565b61270e565b6124ed565b6124c4565b61247f565b61239b565b61229a565b61225c565b612205565b6121e7565b6121c9565b612125565b611fb2565b611f8d565b611f69565b611f2e565b611e10565b611dbf565b611d32565b611c57565b611c3d565b611c23565b611bef565b611bd4565b611bb0565b611b47565b611ad9565b611853565b61175e565b611736565b6112f7565b6111de565b61080e565b61117b565b611141565b611115565b6110fa565b6110e0565b610cd7565b610bfb565b6108ce565b61089b565b610842565b61076c565b610735565b61066f565b6103ca565b6103aa565b5f9103126103a657565b5f80fd5b346103a6575f3660031901126103a657602060cf5460801c604051908152f35b346103a65760203660031901126103a6576001600160801b03600435818116908181036103a657604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1928315610570575f9361053f575b50335f90815261016e6020526040902061046e90612a4b565b9361048085516001600160801b031690565b161561052d57836104c26104b56104a56104db946104a0610529996133ef565b61349f565b83516001600160801b0316612a84565b6001600160801b03168252565b335f90815261016e60205260409020612a9d565b612a9d565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b61056291935060203d602011610569575b61055a81836105f4565b810190612a31565b915f610455565b503d610550565b612a40565b90600182811c921680156105a3575b602083101461058f57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610584565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176105dc57604052565b6105ad565b6001600160401b0381116105dc57604052565b90601f801991011681019081106001600160401b038211176105dc57604052565b5f5b8381106106265750505f910152565b8181015183820152602001610617565b9060209161064f81518092818552858086019101610615565b601f01601f1916010190565b90602061066c928181520190610636565b90565b346103a6575f3660031901126103a6576040515f805461068e81610575565b8084529060209060019081811690811561070b57506001146106c7575b610529856106bb818703826105f4565b6040519182918261065b565b5f80805293505f805160206153168339815191525b8385106106f8575050505081016020016106bb826105296106ab565b80548686018401529382019381016106dc565b869550610529969350602092506106bb94915060ff191682840152151560051b82010192936106ab565b346103a65760203660031901126103a6576020610753600435612ac6565b604051908152f35b6001600160a01b038116036103a657565b346103a65760403660031901126103a6576004356107898161075b565b6001600160a01b038116906024359082156107fc576107c48291335f52600260205260405f209060018060a01b03165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60405163d92e233d60e01b8152600490fd5b346103a6575f3660031901126103a65760206001600160801b0360cf5416604051908152f35b908160809103126103a65790565b60603660031901126103a65760043561085a8161075b565b6024356108668161075b565b604435906001600160401b0382116103a65760209261089461088f610753943690600401610834565b612aec565b349061464f565b346103a65760203660031901126103a6576004356001600160401b0381116103a65761088f610020913690600401610834565b346103a65760603660031901126103a65760048035906108ed8261075b565b60243590604435926108fe8461075b565b61090661396c565b61090e61398d565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af1978815610570575f98610bdc575b50335f90815261016e60205260409020839061099790612a4b565b946001600160801b036109b187516001600160801b031690565b1615610b7a576109c0866133ef565b6109ec6109df6109cf8961349f565b88516001600160801b0316612b40565b6001600160801b03168752565b335f90815260d3602052604090208490610a07905b54612ac6565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa91821561057057610a96928592610a5a925f92610b5b575b506134f5565b92610a6c87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa928315610570575f93610b3c575b505010610b2e5750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e5891610af5610529976104d63360018060a01b03165f5261016e60205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610b53929350803d106105695761055a81836105f4565b905f80610aa8565b610b73919250843d86116105695761055a81836105f4565b905f610a54565b885163752a536d60e01b8152915083828681865afa801561057057610bab610bba9187945f91610bbf575b5061349f565b6001600160801b031687860152565b6109c0565b610bd69150873d89116105695761055a81836105f4565b5f610ba5565b610bf4919850823d84116105695761055a81836105f4565b965f61097c565b346103a65760603660031901126103a657600435610c188161075b565b60243590610c258261075b565b6001600160a01b0381165f8181526002602090815260408083203384529091529020546044359160018201610c75575b610c6984610c6485888361476a565b613a18565b60405160018152602090f35b919093818503948511610ca9575f928352600260209081526040808520338652909152909220939093559180610c69610c55565b612a70565b60609060031901126103a65760043590602435610cca8161075b565b9060443561066c8161075b565b346103a657610ce536610cae565b906001600160a01b03808316156107fc57610cfe61398d565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103a65760408051631d8557d760e01b815260049491905f81878183875af18015610570576110c7575b506001600160a01b0383165f90815261016e60205260409020610d7190612a4b565b6001600160801b03610d8a82516001600160801b031690565b16156110b757610d99816133ef565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa96871561057057610e08975f955f9161107e575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa801561057057610e23925f9161106157506134f5565b95610e41610a018960018060a01b03165f5260d360205260405f2090565b918288118015611051575b61104157908a610e8992610e6788516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa90811561057057670de0b6b3a764000093610ec5938d5f94611018575b5050610eb9610ebf91613248565b92613265565b9161356f565b101561100a578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af1908115610570577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610fe795610f5f93610fec575b5050610f426104b56104a58c61349f565b6001600160a01b0386165f90815261016e60205260409020612a9d565b610f68826140b7565b90610fa6610f8b610f788561349f565b60cf5460801c036001600160801b031690565b6001600160801b0360cf549181199060801b1691161760cf55565b610fb08286614dfc565b610fba8389614009565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b8161100292903d106105695761055a81836105f4565b505f80610f31565b835163185cfc6d60e11b8152fd5b610ebf929450610eb9918161103892903d106105695761055a81836105f4565b9391508d610eab565b865163efda1a2760e01b81528490fd5b5061105a612b5b565b8811610e4c565b61107891508c8d3d106105695761055a81836105f4565b5f610a54565b90506110a391955060a03d60a0116110b0575b61109b81836105f4565b810190613bb1565b509692509050945f610de4565b503d611091565b815163673f032f60e11b81528690fd5b806110d46110da926105e1565b8061039c565b5f610d4f565b346103a6575f3660031901126103a6576020610753612b5b565b346103a6575f3660031901126103a657602060405160128152f35b346103a6575f3660031901126103a657602061112f612b8a565b6040516001600160a01b039091168152f35b346103a6575f3660031901126103a65760206040517f9480c4a5d7e604111fbc986cd90c895a458ca155fe13c10879b93c4592ce29fd8152f35b346103a6575f3660031901126103a6576020610753612bc5565b9060206003198301126103a6576004356001600160401b03928382116103a657806023830112156103a65781600401359384116103a657602484830101116103a6576024019190565b6111e736611195565b905f8051602061539683398151915254916001600160401b0360ff8460401c16159316801590816112ef575b60011490816112e5575b1590816112dc575b506112ca575f80516020615396833981519152805467ffffffffffffffff1916600117905561125891836112a657612c39565b61125e57005b5f80516020615396833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020615396833981519152805460ff60401b1916600160401b179055612c39565b60405163f92ee8a960e01b8152600490fd5b9050155f611225565b303b15915061121d565b849150611213565b346103a65761130536610cae565b906001600160a01b0390818316156107fc5761131f61398d565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103a65760408051631d8557d760e01b815260049291905f81858183875af1801561057057611723575b506001600160a01b0384165f90815261016e6020526040902061139190612a4b565b926001600160801b036113ab85516001600160801b031690565b1615611715576113ba846133ef565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa938415610570575f955f956116e7575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa988915610570575f996116c8575b506001600160a01b038a165f90815260d36020526040902061145990610a01565b90818a1180156116b8575b6116a85761149f908661147e87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa918215610570575f92611687575b506114bd91926134f5565b11611677578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af191821561057057859261165a575b506115068d61349f565b84516001600160801b03169061151b91612a84565b6001600160801b031684526001600160a01b038a165f90815261016e602052604090208461154891612a9d565b611551896140b7565b9761155b8a61349f565b60cf5460801c036001600160801b031661158a906001600160801b0360cf549181199060801b1691161760cf55565b611594898c614dfc565b6001600160a01b038b165f90815260d360205260409020546115b590612ac6565b906115bf916134f5565b935187519182526001600160801b0316868201908152909283918290036020019082905afa928315610570575f9361163b575b50501161162d575091610fe7917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610fba8389614009565b9051631d8fa13d60e31b8152fd5b611652929350803d106105695761055a81836105f4565b905f806115f2565b61167090833d85116105695761055a81836105f4565b505f6114fc565b855163324b20e160e11b81528590fd5b6114bd92506116a290883d8a116105695761055a81836105f4565b916114b2565b875163efda1a2760e01b81528790fd5b506116c1612b5b565b8a11611464565b6116e0919950853d87116105695761055a81836105f4565b975f611438565b61142592965061170791955060a03d60a0116110b05761109b81836105f4565b505050959095949091611401565b905163673f032f60e11b8152fd5b806110d4611730926105e1565b5f61136f565b346103a6575f3660031901126103a657609c546040516001600160a01b039091168152602090f35b346103a65760203660031901126103a65760043561177b8161075b565b60018060a01b03165f5261016e602052602060405f206040519061179e826105c1565b54906001600160801b03918281169081835260801c848301526117c6575b5116604051908152f35b6117cf816133ef565b6117bc565b6040519060a082018281106001600160401b038211176105dc57604052565b60405190611800826105c1565b565b6001600160401b0381116105dc57601f01601f191660200190565b92919261182982611802565b9161183760405193846105f4565b8294818452818301116103a6578281602093845f960137010152565b6040806003193601126103a657600490813561186e8161075b565b6024356001600160401b0381116103a657366023820112156103a65761189d903690602481870135910161181d565b916118a6613df0565b8051926118dd846118cf60209363439fab9160e01b858401528460248401526044830190610636565b03601f1981018652856105f4565b6118e5613df0565b6118ed6140a3565b6001600160a01b03838116801592919087908415611aa4575b8415611a36575b84156119d2575b5050821561193c575b505061192d576100208383614a39565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa918215610570575f926119a5575b5050155f8061191d565b6119c49250803d106119cb575b6119bc81836105f4565b810190612daf565b5f8061199b565b503d6119b2565b855163054fd4d560e41b81529294508391839182905afa9081156105705760029160ff915f91611a09575b5016141591865f611914565b611a299150843d8611611a2f575b611a2181836105f4565b810190614a24565b5f6119fd565b503d611a17565b935050835163198ca60560e11b815282818981875afa9081156105705788917f9480c4a5d7e604111fbc986cd90c895a458ca155fe13c10879b93c4592ce29fd915f91611a87575b5014159361190d565b611a9e9150853d87116105695761055a81836105f4565b5f611a7e565b5f80516020615336833981519152549094508490611ad2906001600160a01b03165b6001600160a01b031690565b1493611906565b346103a65760203660031901126103a6576004356001600160a01b03611afd612d84565b163303611b355780610107555f61010855337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346103a6575f3660031901126103a6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611b9e5760206040515f805160206153368339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126103a6576001600160a01b03611bcb612b8a565b163303611b3557005b346103a6575f3660031901126103a657602060405160018152f35b346103a6575f3660031901126103a6575f80516020615336833981519152546040516001600160a01b039091168152602090f35b346103a6575f3660031901126103a6576020610753612d76565b346103a6575f3660031901126103a657602061112f612d84565b346103a65760203660031901126103a65760d180549081905f6004355b848210611ca557505050811015611c9a57610529905b6040519081529081906020820190565b506105295f19611c8a565b909193808316906001818518811c8301809311610ca9575f8790525f805160206153768339815191528301546001600160a01b0316841015611cec575050935b9190611c74565b909591019250611ce5565b346103a65760203660031901126103a657600435611d148161075b565b60018060a01b03165f5260d3602052602060405f2054604051908152f35b346103a6575f3660031901126103a657604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa8015610570576020915f91611da2575b506040519015158152f35b611db99150823d84116119cb576119bc81836105f4565b5f611d97565b346103a65760803660031901126103a657610529611df3600435611de28161075b565b606435906044359060243590612dd1565b604080519384526020840192909252908201529081906060820190565b346103a6576040806003193601126103a65760043560243591611e328361075b565b611e3a61522f565b8115611f1e576001600160a01b0383168015611f0d57611e5983612ac6565b928315611efc57611e68612b5b565b8411611eeb57611e9f8461052996611e90610f8b611e858461349f565b60cf5460801c612a84565b611e9a8433614dfc565b614009565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea8348090604090a3611edd33613a18565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346103a65760203660031901126103a657600435611f4b8161075b565b60018060a01b03165f526003602052602060405f2054604051908152f35b346103a6575f3660031901126103a657602061ffff609c5460a01c16604051908152f35b346103a65760603660031901126103a657610529611df3604435602435600435612e4b565b346103a6576040806003193601126103a6576004359060243590611fd58261075b565b611fdd61396c565b8215611f1e576001600160a01b038216928315611f0d57610529936120be6120a28361202061201460d0546001600160801b031690565b6001600160801b031690565b816120806120358361203061524f565b612e3e565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a61206f81608081015b03601f1981018352826105f4565b5190205f5260d260205260405f2090565b55335f90815260d36020526040902061209a838254612dc4565b90550161349f565b6001600160801b03166001600160801b031960d054161760d055565b82518481526020810183905233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f90604090a36120fb33613a18565b8151908152309033905f8051602061535683398151915290602090a3519081529081906020820190565b346103a6575f3660031901126103a6576040515f6001805461214681610575565b808552916020916001811690811561070b575060011461217057610529856106bb818703826105f4565b60015f90815293507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8385106121b6575050505081016020016106bb826105296106ab565b805486860184015293820193810161219a565b346103a6575f3660031901126103a657602061010754604051908152f35b346103a6575f3660031901126103a657602061010854604051908152f35b346103a6576122577f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf61223736611195565b92906122416140a3565b6040519182916020835233956020840191612fdf565b0390a2005b346103a65760403660031901126103a65761228660043561227c8161075b565b602435903361476a565b61228f33613a18565b602060405160018152f35b346103a65760203660031901126103a6576004356122b78161075b565b6122bf6140a3565b6001600160a01b031680156107fc5761010980546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156103a6578235916001600160401b0383116103a6576020808501948460051b0101116103a657565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b84831061236d5750505050505090565b909192939495848061238b600193603f198682030187528a51610636565b980193019301919493929061235d565b346103a65760203660031901126103a657600480356001600160401b0381116103a6576123cc903690600401612308565b916123d683613016565b925f5b8181106123ee57604051806105298782612338565b5f806123fb8385886130a5565b6040939161240d8551809381936130c5565b0390305af49061241b6130d2565b9115612442575090600191612430828861316c565b5261243b818761316c565b50016123d9565b848260448151106103a657612466818361247b930151602480918301019101613101565b925162461bcd60e51b8152928392830161065b565b0390fd5b346103a6575f3660031901126103a65761052960405161249e816105c1565b60058152640352e302e360dc1b6020820152604051918291602083526020830190610636565b346103a65760203660031901126103a65760206107536004356140b7565b60ff8116036103a657565b346103a65760e03660031901126103a65760043561250a8161075b565b6024356125168161075b565b60443590606435926084359061252b826124e2565b6001600160a01b038381169590929086156107fc574281106126fc576020915f9161261e61262a89878a6125e1612560612bc5565b6001600160a01b0384165f9081526003602052604090209097908054906001820190556040519586948d8601968791959493909260a09360c08401977f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98552600180871b038092166020860152166040840152606083015260808201520152565b03916125f5601f19938481018352826105f4565b5190206040519384918983019687909160429261190160f01b8352600283015260228201520190565b039081018352826105f4565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa15610570575f519282841680159081156126ef575b506126dd576126ca85916126b57f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259660018060a01b03165f52600260205260405f2090565b9060018060a01b03165f5260205260405f2090565b5560405193845216918060208101610fe7565b6040516323389ba560e21b8152600490fd5b905083831614155f612670565b604051631ab7da6b60e01b8152600490fd5b346103a6575f3660031901126103a65760206001600160801b0360d05416604051908152f35b60409060031901126103a65760043561274c8161075b565b9060243561066c8161075b565b346103a657602061279461276c36612734565b6001600160a01b039182165f9081526002855260408082209290931681526020919091522090565b54604051908152f35b346103a65760203660031901126103a6576100206004356127bd8161075b565b6127c56140a3565b614146565b908160a09103126103a65790565b346103a65760803660031901126103a6576001600160401b036004358181116103a6576128099036906004016127ca565b6024358281116103a657612821903690600401612308565b6044929192358481116103a65761283c903690600401612308565b916064359586116103a657612858610020963690600401612308565b95909461327c565b346103a6576040806003193601126103a6576004906001600160401b0382358181116103a65761289390369085016127ca565b906024359081116103a6576128ab9036908501612308565b9390926128b661398d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156103a6575f8251809263837d444160e01b82528183816129058a8a83016131b1565b03925af18015610570576129e0575b506801bc16d674ec800000612927612b5b565b106129d3578083019360b061293c8686613073565b9050036129c557612990612994916101085497610107549061298361297b8b6129658c8c613073565b6120618b949294519384926020840196876133b1565b5190206133ce565b602081519101209261443c565b1590565b6129b8576100206001866129b16129ab8888613073565b90614474565b0161010855565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b806110d46129ed926105e1565b5f612914565b346103a6575f3660031901126103a6576037546040516001600160a01b039091168152602090f35b6020610753612a2936612734565b90349061464f565b908160209103126103a6575190565b6040513d5f823e3d90fd5b90604051612a58816105c1565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211610ca957565b815160209092015160801b6001600160801b0319166001600160801b0392909216919091179055565b60cf546001600160801b0381169081612ade57505090565b9161066c9260801c9061356f565b612af5906136d7565b9080612b31575b50612b0357565b612b0b614cff565b80612b14575b50565b5f906040519081525f8051602061535683398151915260203092a3565b612b3a9061386d565b5f612afc565b9190916001600160801b0380809416911601918211610ca957565b4760d054612b716001600160801b038216612ac6565b9060801c01908181115f14612b84570390565b50505f90565b6101a1546001600160a01b03168015612ba05790565b507f000000000000000000000000000000000000000000000000000000000000000090565b467f000000000000000000000000000000000000000000000000000000000000000003612bf25760045490565b61066c613bd8565b908160209103126103a6575161066c8161075b565b359061ffff821682036103a657565b9080601f830112156103a65781602061066c9335910161181d565b60405163e7f6f22560e01b815290916020918281600481335afa908115610570575f91612d59575b50604051636f4fa30f60e01b8152918383600481335afa928315610570575f93612d2a575b50840183858203126103a65784356001600160401b03958682116103a657019060a0828203126103a657612cb86117d4565b9482358652612cc8818401612c0f565b9086015260408201358681116103a65781612ce4918401612c1e565b604086015260608201358681116103a65781612d01918401612c1e565b606086015260808201359586116103a65761180095612d209201612c1e565b6080840152613cfe565b612d4b919350843d8611612d52575b612d4381836105f4565b810190612bfa565b915f612c86565b503d612d39565b612d709150833d8511612d5257612d4381836105f4565b5f612c61565b60d4548061066c57505f1990565b610109546001600160a01b0390811680612da057506037541690565b905090565b801515036103a657565b908160209103126103a6575161066c81612da5565b91908203918211610ca957565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612e21929091612e0a8160808101612061565b5190205f5260d260205260405f2054928391613e6e565b9091828103908111610ca95792565b9060018201809211610ca957565b91908201809211610ca957565b929190915f93612e7b7f000000000000000000000000000000000000000000000000000000000000000085612e3e565b4210612fb55760408051336020820190815291810186905260608082018490528152601f1991612ebc91612eb06080826105f4565b51902094868433612dd1565b9096909587878115612fa75750505f90815260d2602052604081205560018211612f60575b505050612f19612efe612ef38561349f565b60d05460801c612a84565b6001600160801b0360d0549181199060801b1691161760d055565b612f238333614009565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b612f9e91929750612f718785612e3e565b6040805133602082019081529181019390935260608301829052909890919061206f90826080810161261e565b555f8080612ee1565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116105dc5760051b60200190565b9061302082612fff565b61302d60405191826105f4565b828152809261303e601f1991612fff565b01905f5b82811061304e57505050565b806060602080938501015201613042565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156103a657018035906001600160401b0382116103a6576020019181360383136103a657565b908210156130c0576130bc9160051b810190613073565b9091565b61305f565b908092918237015f815290565b3d156130fc573d906130e382611802565b916130f160405193846105f4565b82523d5f602084013e565b606090565b6020818303126103a6578051906001600160401b0382116103a6570181601f820112156103a657805161313381611802565b9261314160405194856105f4565b818452602082840101116103a65761066c9160208085019101610615565b8051156130c05760200190565b80518210156130c05760209160051b010190565b9035601e19823603018112156103a65701602081359101916001600160401b0382116103a65781360383136103a657565b9060a061066c926020815282356020820152602083013560408201526131ed6131dd6040850185613180565b84606085015260c0840191612fdf565b906132206132156132016060870187613180565b601f19858703810160808701529591612fdf565b946080810190613180565b93909282860301910152612fdf565b906801bc16d674ec8000009180830292830403610ca957565b90670de0b6b3a764000091828102928184041490151715610ca957565b9061271091828102928184041490151715610ca957565b92909493919561328a61398d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156103a6576040965f8851809263837d444160e01b82528183816132de8c600483016131b1565b03925af180156105705761339e575b506132f6612b5b565b6132ff8961322f565b1161338d5787158015613373575b613362579161333e95939161333889612990979561333261010754978c810190613073565b906142b6565b9461442a565b613352575061180090610108540161010855565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061338087860186613073565b905060b08902141561330d565b86516396d8043360e01b8152600490fd5b806110d46133ab926105e1565b5f6132ed565b9392916020916133c991604087526040870191612fdf565b930152565b9060405191602083015260208252611800826105c1565b612b113433614587565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f91613480575b5060208201916001600160801b03918284511691828214613479578361346c6104a061347495858486511661356f565b16905261349f565b169052565b5050505050565b613499915060203d6020116105695761055a81836105f4565b5f61343c565b6001600160801b03908181116134b3571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156134f0570490565b6134d2565b90808202905f1981840990828083109203918083039214613564576127109082821115613552577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146135e2578483111561355257829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061066c92506134e6565b908160609103126103a6578051916040602083015192015161066c81612da5565b81835290916001600160fb1b0383116103a65760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036103a657604083015260408101356136638161075b565b6001600160a01b031660608381019190915281013536829003601e19018112156103a65701602081359101906001600160401b0381116103a6578060051b360382136103a65760a08360808061066c9601520191613610565b9190915f8382019384129112908015821691151617610ca957565b6040516325f56f1160e01b81526001600160a01b039291606090829081906137029060048301613634565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af1928315610570575f915f905f95613828575b5084156137d5578161374c612b8a565b16917f00000000000000000000000000000000000000000000000000000000000000001682146137ce57509060205f92600460405180958193634641257d60e01b83525af1908115610570576137a9925f926137ad575b506136bc565b9190565b6137c791925060203d6020116105695761055a81836105f4565b905f6137a3565b90816137db575b50509190565b803b156103a657604051636ee3193160e11b815260048101929092525f908290602490829084905af1801561057057613815575b806137d5565b806110d4613822926105e1565b5f61380f565b9194505061384e915060603d606011613856575b61384681836105f4565b8101906135ef565b93905f61373c565b503d61383c565b600160ff1b8114610ca9575f0390565b61387c61201460cf5460801c90565b5f8212613953578161388d91612e3e565b9061389a610f8b8361349f565b6138af609c549161ffff8360a01c16906134f5565b801561394e57807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc35318686547936138ed61201460cf546001600160801b031690565b8061393857505061393390925b6001600160a01b03169161390e8484614c97565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613933926139489203908461356f565b926138fa565b505050565b6104a0610f8b916139666118009461385d565b90612dc4565b6139746146fb565b1561397b57565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f916139f9575b506139e757565b60405163e775715160e01b8152600490fd5b613a12915060203d6020116119cb576119bc81836105f4565b5f6139e0565b6001600160a01b0381165f90815261016e60205260409020613a3990612a4b565b906001600160801b03613a5383516001600160801b031690565b1615613bad57610a01613a8a91613a6861398d565b613a71846133ef565b6001600160a01b03165f90815260d36020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa91821561057057613aed8693613afb92613b27965f92613b9557506134f5565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa928315610570575f93613b76575b505010613b6457565b604051633684c65960e01b8152600490fd5b613b8d929350803d106105695761055a81836105f4565b905f80613b5b565b610b73919250863d88116105695761055a81836105f4565b5050565b908160a09103126103a6578051916020820151916040810151916080606083015192015190565b6040515f905f5490613be982610575565b9283825260209384830193600190866001821691825f14613cde575050600114613c9b575b50509181613c24613c95936120619503826105f4565b519020604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f95810195865260208601929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69085015246606085015230608085015291829060a0850190565b51902090565b5f80805286935091905f805160206153168339815191525b828410613cc95750505082010181613c24613c0e565b80548685018601528794909301928101613cb3565b60ff1916875292151560051b85019092019250839150613c249050613c0e565b919091613d096147e6565b6080820151613d166147e6565b603780546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190613d65908261065b565b0390a2602082015192613d766147e6565b61271061ffff851611613dde57613dd693613d93613dc693614146565b609c549061ffff60a01b9060a01b169061ffff60a01b191617609c55613db98351614814565b613dc1614844565b614865565b6060604082015191015190614894565b6118006149c1565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613e2e575b5050611b9e57565b5f805160206153368339815191525416141590505f80613e26565b90604051613e56816105c1565b91546001600160a01b038116835260a01c6020830152565b60d1545f948594939091808410801590614001575b613ff45783613fbe575f5b60d15f526001600160a01b0316613eb35f805160206153768339815191528601613e49565b8051909790613eca906001600160a01b0316611ac6565b98613eef613ee36020809b01516001600160601b031690565b6001600160601b031690565b948381108015613fb4575b613fa25791600193979a95613f19613f25939488035b838c0390614ae4565b8092019887039161356f565b01970193808611801590613f98575b613f8d5760d15f528290613f565f805160206153768339815191528701613e49565b805190890151969992966001600160a01b039091169460019392613f259290916001600160601b0390911690613f19908803613f10565b945050509250509190565b5081851015613f34565b60405163e8722f8f60e01b8152600490fd5b50808b1115613efa565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce28401546001600160a01b0316613e8e565b505093505050505f905f90565b508415613e83565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f009160028354146140915760028355814710614079575f918291829182916001600160a01b03165af161405b6130d2565b50156140675760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b6037546001600160a01b03163303611b3557565b60cf54906001600160801b038216811580156140e6575b156140d95750905090565b61066c9260801c9161356f565b5080156140ce565b60cf546001600160801b038116908215801561413e575b1561410f57505090565b60801c9061411e82828561356f565b9282156134f0570961412d5790565b600181018091111561066c57612a70565b508115614105565b61414e61398d565b6001600160a01b0316801561419657609c80546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b906141b282612fff565b6141bf60405191826105f4565b82815280926141d0601f1991612fff565b0190602036910137565b906030116103a65790603090565b906090116103a65760300190606090565b9060b0116103a65760900190602090565b909392938483116103a65784116103a6578101920390565b90156130c05790565b91908110156130c05760051b0190565b359060208110614249575090565b5f199060200360031b1b1690565b969594906133c993614278614286926060979560808c5260808c0191612fdf565b9089820360208b0152610636565b918783036040890152612fdf565b90602061066c928181520190612fc7565b91602061066c938181520191612fdf565b9193929061010854925f925f906142cc816141a8565b976142d5614af1565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106143165750505050505050505050565b60b061432691018099898561420a565b9960409a8d6143628d5161434a6020918281019061297b816120618c8a8d876133b1565b80519101209161435b858b8b61422b565b359061316c565b5261436d81846141da565b909361438d61438761437f85846141e8565b9590936141f9565b9061423b565b908a3b156103a6578b8f5f936143b8915196879485946304512a2360e31b8652888c60048801614257565b03816801bc16d674ec8000008d5af19384156105705761440b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298614417575b5097019e51928392836142a5565b0390a101989097614303565b806110d4614424926105e1565b5f6143fd565b906144389495939291614b32565b1490565b9192915f915b808310614450575050501490565b90919261446b60019161446486858761422b565b35906150b1565b93019190614442565b816030116103a657614387917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166144b2614af1565b906144c96144c084866141e8565b969094866141f9565b94813b156103a6576801bc16d674ec8000005f9461452f97604051988996879586946304512a2360e31b86526080600487015261452061450d8d6084890190612fc7565b60031994858983030160248a0152610636565b92868403016044870152612fdf565b90606483015203925af1908115610570577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261393392614578575b5060405191829182614294565b614581906105e1565b5f61456b565b919061459161398d565b6001600160a01b0383169081156107fc57801561463d57806145b861201460cf5460801c90565b01936145c2612d76565b851161462b57610f8b946145e9916145e46145dc856140ee565b97889361349f565b614c97565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b9092919261465b61398d565b6001600160a01b0382169182156107fc57811561463d578161468261201460cf5460801c90565b0161468b612d76565b811161462b57610f8b956146d2614626927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c946145e46146ca886140ee565b9a8b9361349f565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610570575f91614751575090565b61066c915060203d6020116119cb576119bc81836105f4565b6001600160a01b039081169190821580156147dc575b6107fc57825f5260d360205260405f2090815492858403938411610ca9575f8051602061535683398151915293602093556147cb8160018060a01b03165f5260d360205260405f2090565b8681540190556040519586521693a3565b5080821615614780565b60ff5f805160206153968339815191525460401c161561480257565b604051631afcd79f60e31b8152600490fd5b61481c6147e6565b8015614832576001810161482d5750565b60d455565b6040516331278a8760e01b8152600490fd5b61484c6147e6565b6801bc16d674ec80000061485e612d76565b1061483257565b61486d6147e6565b6001600160a01b03168061487e5750565b6101a180546001600160a01b0319169091179055565b61489c6147e6565b601e81511180156149b6575b6149a4576148b46147e6565b8051906001600160401b0382116105dc576148d8826148d35f54610575565b614e67565b602090816001601f8511146149305750918061490e9261491595945f92614925575b50508160011b915f199060031b1c19161790565b5f55614f31565b611800614920613bd8565b600455565b015190505f806148fa565b5f80529190601f1984165f80516020615316833981519152935f905b82821061498c57505091600193918561491597969410614974575b505050811b015f55614f31565b01515f1960f88460031b161c191690555f8080614967565b8060018697829497870151815501960194019061494c565b604051632d3f993760e21b8152600490fd5b50600a8251116148a8565b6149c96147e6565b6149d16147e6565b6149d96147e6565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca003410614a1257612b113430614587565b60405163ea2559bb60e01b8152600490fd5b908160209103126103a6575161066c816124e2565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614ac3575b50614a8957604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206153368339815191528403614aaa5761180092935061500f565b604051632a87526960e21b815260048101859052602490fd5b614add91955060203d6020116105695761055a81836105f4565b935f614a63565b9080821015612da0575090565b604051600160f81b60208201525f60218201523060601b602c8201526020815261066c816105c1565b5f198114610ca95760010190565b3561066c81612da5565b9293919091805193614b448486612e3e565b614b4d87612e30565b03614b8f57614b5b866141a8565b945f8094885f965f5b828110614bc7575050159150614ba190505750505003614b8f57614b8b915f19019061316c565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614bb9575050614b8b9061315f565b614bc39250614222565b3590565b8a86861015614c7a5750614bf9614bf482614beb614be489614b1a565b988c61316c565b51955b8761422b565b614b28565b15614c5f578a86861015614c3e5750614c2a60019293614c22614c1b88614b1a565b978b61316c565b515b906150b1565b614c34828d61316c565b5201908a91614b64565b92614c2a90614c5984614c5360019691614b1a565b9661316c565b51614c24565b614c2a60019293614464614c728c614b1a565b9b8d8b61422b565b91614bf482614c9083614c53614bf99591614b1a565b5195614bee565b5f8051602061535683398151915260205f92614cb28561349f565b60cf5490614cca6001600160801b0391828416612b40565b6001600160801b031990921691161760cf556001600160a01b031680845260d3825260408085208054870190555194855293a3565b60d054906001600160801b038216918215614df65760801c614d33614d248247612dc4565b614d2d85612ac6565b90614ae4565b908115614def57614d43826140b7565b938415614de75782614d6f612efe6104a061180096610f8b966120306120a26104a08d611e859a612dc4565b614d79818761512b565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16104a0614dcb614dba8861349f565b60cf546001600160801b0316612a84565b6001600160801b03166001600160801b031960cf54161760cf55565b505f93505050565b505f925050565b505f9150565b6001600160a01b03165f81815260d360205260409020805483810391908211610ca9575f935f805160206153568339815191529260209255614e3d8161349f565b60cf54906001600160801b03908183160316906001600160801b0319161760cf55604051908152a3565b601f8111614e73575050565b5f80525f80516020615316833981519152906020601f840160051c83019310614eb6575b601f0160051c01905b818110614eab575050565b5f8155600101614ea0565b9091508190614e97565b90601f8211614ecd575050565b60019160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906020601f840160051c83019310614f27575b601f0160051c01905b818110614f1d57505050565b5f81558201614f11565b9091508190614f08565b9081516001600160401b0381116105dc57600190614f5881614f538454610575565b614ec0565b602080601f8311600114614f8d57508190614f899394955f926149255750508160011b915f199060031b1c19161790565b9055565b90601f19831695614fbf60015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690565b925f905b888210614ff85750508385969710614fe0575b505050811b019055565b01515f1960f88460031b161c191690555f8080614fd6565b808785968294968601518155019501930190614fc3565b90813b15615090575f8051602061533683398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561507557612b1191615212565b50503461507e57565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b818110156150c5575f5260205260405f2090565b905f5260205260405f2090565b60d15490600160401b8210156105dc57600182018060d1558210156130c05760d15f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f8051602061537683398151915290910155565b908115801561520a575b6151f85760d154806151c257505f905b6001600160a01b03918216928301928310610ca9578183116151a257611800929161518d61517561519d93615291565b9161517e6117f3565b94166001600160a01b03168452565b6001600160601b03166020830152565b6150d2565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b031690615145565b604051632ec8835b60e21b8152600490fd5b508015615135565b5f8061066c93602081519101845af46152296130d2565b916152c4565b6152376146fb565b61523d57565b6040516389a1dc6360e01b8152600490fd5b60d1548061525c57505f90565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b0316611ac6565b6001600160601b03908181116152a5571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b906152d9575080511561406757805190602001fd5b8151158061530c575b6152ea575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156152e256fe290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce3f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212201b7a2a4606a5e03acc6b226b34e17aaa62090ae9ec2eb74766012a9b7091a63064736f6c63430008160033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/shared/artifacts/EthGenesisVault.json b/test/shared/artifacts/EthGenesisVault.json new file mode 100644 index 00000000..f5ec70f1 --- /dev/null +++ b/test/shared/artifacts/EthGenesisVault.json @@ -0,0 +1,1709 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EthGenesisVault", + "sourceName": "contracts/vaults/ethereum/EthGenesisVault.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_validatorsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenVaultController", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "sharedMevEscrow", + "type": "address" + }, + { + "internalType": "address", + "name": "poolEscrow", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardEthToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitingAssetsClaimDelay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "CapacityExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimTooEarly", + "type": "error" + }, + { + "inputs": [], + "name": "Collateralized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeePercent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHealthFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialHarvest", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLtv", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPosition", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecurityDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShares", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidators", + "type": "error" + }, + { + "inputs": [], + "name": "LowLtv", + "type": "error" + }, + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + }, + { + "inputs": [], + "name": "NotCollateralized", + "type": "error" + }, + { + "inputs": [], + "name": "NotHarvested", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "RedemptionExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintToInt", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeFailed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "capacity", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "feePercent", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "GenesisVaultCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Migrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptPoolEscrowOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "migrate", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keysManager_", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6101c0346200029b576200512b6001600160401b03601f38839003908101601f1916840190828211858310176200029f5780859460409384528539610120938491810103126200029b576200005484620002b3565b6200006260208601620002b3565b9262000070838701620002b3565b926200007f60608801620002b3565b6200008d60808901620002b3565b926200009c60a08a01620002b3565b94620000ab60c08b01620002b3565b96620000ba60e08c01620002b3565b98610100809c01519260805260a05260c0523060e052895260018060a01b03809216885281610140941684526101609485527ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff82861c166200028a57808083160362000245575b50505080610180951685526101a0951685525194614e629687620002c98839608051878181611a47015281816123f50152818161272401528181613122015281816135b70152818161399301526144fb015260a0518761168d015260c051878181613f70015261411a015260e0518781816118790152613b2301525186612ce90152518581816103950152818161062f015281816109bc01528181610fe0015281816132c9015261485501525184818161070b01528181610a680152818161108c01526147d4015251838181612b1201526135ff015251828181610907015281816121f0015281816129b601528181612aa00152818161327a0152818161384f01526148dd0152518181816120e90152818161276c01526129550152f35b6001600160401b0319909116811790915582519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f808062000127565b845163f92ee8a960e01b8152600490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036200029b5756fe60806040526004361015610022575b3615610018575f80fd5b610020613278565b005b5f3560e01c806301e1d11414610301578063066055e0146102fc57806307a2d13a146102f757806318f72950146102f25780631a7ff553146102ed578063201b9eb5146102e857806323d18ed8146102e35780632999ad3f146102de5780632cdf7401146102d95780633229fa95146102d457806333194c0a146102cf5780633a98ef39146102ca578063439fab91146102c557806343e82a79146102c057806346904840146102bb5780634ec96b22146102b65780634f1ef286146102b1578063514e2708146102ac57806352d1902d146102a757806353156f28146102a257806354fd4d501461029d5780635c60da1b146102985780635cfc1a51146102935780635dddf3a81461028e57806360d60e6e1461028957806372b410a81461028457806376b58b901461027f5780637bde82f21461027a5780637fd6f15c146102755780638697d2c2146102705780638ceab9aa1461026b5780639b401cde14610266578063a1bf49aa14610261578063a49a1e7d1461025c578063aaa4e83614610257578063ac9650d814610252578063ad3cb1cc1461024d578063ad68ebf714610248578063c6e6f59214610243578063d83ad00c1461023e578063e74b981b14610239578063ef2a215814610234578063f04da65b1461022f578063f5e9de4d1461022a578063f851a440146102255763f9609f080361000e57612554565b61252d565b61239d565b612362565b6122da565b61229f565b612279565b61225b565b6120bd565b612078565b611f83565b611e3d565b611de6565b611dc9565b611dac565b611c66565b611c41565b611c1d565b611afa565b611aa9565b611a1c565b611977565b61195d565b611943565b61190f565b6118f4565b6118d0565b611867565b6117fb565b611575565b61141c565b6113f4565b610fb5565b610e9c565b610e2d565b610df3565b610dc7565b610dad565b610992565b6108ec565b6105bf565b61058c565b610533565b6104ee565b610345565b610314565b5f91031261031057565b5f80fd5b34610310575f36600319011261031057602060985460801c604051908152f35b6001600160801b0381160361031057565b346103105760203660031901126103105760043561036281610334565b604051633b9e9f0160e21b81523360048201526001600160801b03821660248201526020816044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19081156104e9575f916104ba575b50335f908152610137602052604090206103de90612598565b916001600160801b03806103f985516001600160801b031690565b16156104a8578361043d610430610420610456946104196104a4996132b4565b8616613369565b83516001600160801b03166125d1565b6001600160801b03168252565b335f908152610137602052604090206125ea565b6125ea565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104dc915060203d6020116104e2575b6104d481836114f4565b81019061257e565b5f6103c5565b503d6104ca565b61258d565b3461031057602036600319011261031057602061050c60043561261c565b604051908152f35b6001600160a01b0381160361031057565b908160809103126103105790565b60603660031901126103105760043561054b81610514565b60243561055781610514565b604435906001600160401b0382116103105760209261058561058061050c943690600401610525565b6126f6565b34906142e7565b34610310576020366003190112610310576004356001600160401b03811161031057610580610020913690600401610525565b346103105760603660031901126103105760048035906105de82610514565b60243590604435926105ef84610514565b6105f7613957565b6105ff613978565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104e9575f986108cd575b50335f90815261013760205260409020839061068890612598565b946001600160801b036106a287516001600160801b031690565b161561086b576106b1866132b4565b6106dd6106d06106c089613369565b88516001600160801b0316612a83565b6001600160801b03168752565b335f908152609c6020526040902084906106f8905b5461261c565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104e95761078792859261074b925f9261084c575b506133bf565b9261075d87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104e9575f9361082d575b50501061081f5750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916107e66104a4976104513360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610844929350803d106104e2576104d481836114f4565b905f80610799565b610864919250843d86116104e2576104d481836114f4565b905f610745565b885163752a536d60e01b8152915083828681865afa80156104e95761089c6108ab9187945f916108b0575b50613369565b6001600160801b031687860152565b6106b1565b6108c79150873d89116104e2576104d481836114f4565b5f610896565b6108e5919850823d84116104e2576104d481836114f4565b965f61066d565b34610310575f8060031936011261031057610905613a03565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610310575f809160046040518094819363b4b6d74f60e01b83525af180156104e95761095c575080f35b61002091506114a6565b6060906003190112610310576004359060243561098281610514565b9060443561098f81610514565b90565b34610310576109a036610966565b906001600160a01b0380831615610d9b576109b9613978565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103105760408051631d8557d760e01b815260049491905f81878183875af180156104e957610d82575b506001600160a01b0383165f90815261013760205260409020610a2c90612598565b6001600160801b03610a4582516001600160801b031690565b1615610d7257610a54816132b4565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104e957610ac3975f955f91610d39575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104e957610ade925f91610d1c57506133bf565b95610afc6106f28960018060a01b03165f52609c60205260405f2090565b918288118015610d0c575b610cfc57908a610b4492610b2288516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104e957670de0b6b3a764000093610b80938d5f94610cd3575b5050610b74610b7a916130de565b926130fb565b91613439565b1015610cc5578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104e9577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610ca295610c1a93610ca7575b5050610bfd6104306104208c613369565b6001600160a01b0386165f908152610137602052604090206125ea565b610c2382613e4e565b90610c61610c46610c3385613369565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610c6b828661454f565b610c758389613d32565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610cbd92903d106104e2576104d481836114f4565b505f80610bec565b835163185cfc6d60e11b8152fd5b610b7a929450610b749181610cf392903d106104e2576104d481836114f4565b9391508d610b66565b865163efda1a2760e01b81528490fd5b50610d15612a9e565b8811610b07565b610d3391508c8d3d106104e2576104d481836114f4565b5f610745565b9050610d5e91955060a03d60a011610d6b575b610d5681836114f4565b810190613a16565b509692509050945f610a9f565b503d610d4c565b815163673f032f60e11b81528690fd5b80610d8f610d95926114a6565b80610306565b5f610a0a565b60405163d92e233d60e01b8152600490fd5b34610310575f36600319011261031057602061050c612a9e565b34610310575f366003190112610310576020610de1612af9565b6040516001600160a01b039091168152f35b34610310575f3660031901126103105760206040517f11a6b7bef0f97d298d56e5af2aa94330353808e861cbac86172faad21b10c5058152f35b34610310575f3660031901126103105760206001600160801b0360985416604051908152f35b906020600319830112610310576004356001600160401b039283821161031057806023830112156103105781600401359384116103105760248483010111610310576024019190565b610ea536610e53565b905f80516020614e0d83398151915254916001600160401b0360ff8460401c1615931680159081610fad575b6001149081610fa3575b159081610f9a575b50610f88575f80516020614e0d833981519152805467ffffffffffffffff19166001179055610f169183610f6457612b63565b610f1c57005b5f80516020614e0d833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020614e0d833981519152805460ff60401b1916600160401b179055612b63565b60405163f92ee8a960e01b8152600490fd5b9050155f610ee3565b303b159150610edb565b849150610ed1565b3461031057610fc336610966565b906001600160a01b039081831615610d9b57610fdd613978565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103105760408051631d8557d760e01b815260049291905f81858183875af180156104e9576113e1575b506001600160a01b0384165f9081526101376020526040902061104f90612598565b926001600160801b0361106985516001600160801b031690565b16156113d357611078846132b4565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104e9575f955f956113a5575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104e9575f99611386575b506001600160a01b038a165f908152609c60205260409020611117906106f2565b90818a118015611376575b6113665761115d908661113c87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104e9575f92611345575b5061117b91926133bf565b11611335578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104e9578592611318575b506111c48d613369565b84516001600160801b0316906111d9916125d1565b6001600160801b031684526001600160a01b038a165f9081526101376020526040902084611206916125ea565b61120f89613e4e565b976112198a613369565b60985460801c036001600160801b0316611248906001600160801b036098549181199060801b16911617609855565b611252898c61454f565b6001600160a01b038b165f908152609c60205260409020546112739061261c565b9061127d916133bf565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104e9575f936112f9575b5050116112eb575091610ca2917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610c758389613d32565b9051631d8fa13d60e31b8152fd5b611310929350803d106104e2576104d481836114f4565b905f806112b0565b61132e90833d85116104e2576104d481836114f4565b505f6111ba565b855163324b20e160e11b81528590fd5b61117b925061136090883d8a116104e2576104d481836114f4565b91611170565b875163efda1a2760e01b81528790fd5b5061137f612a9e565b8a11611122565b61139e919950853d87116104e2576104d481836114f4565b975f6110f6565b6110e39296506113c591955060a03d60a011610d6b57610d5681836114f4565b5050509590959490916110bf565b905163673f032f60e11b8152fd5b80610d8f6113ee926114a6565b5f61102d565b34610310575f366003190112610310576065546040516001600160a01b039091168152602090f35b346103105760203660031901126103105760043561143981610514565b60018060a01b03165f52610137602052602060405f206040519061145c826114be565b54906001600160801b03918281169081835260801c84830152611484575b5116604051908152f35b61148d816132b4565b61147a565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116114b957604052565b611492565b604081019081106001600160401b038211176114b957604052565b606081019081106001600160401b038211176114b957604052565b90601f801991011681019081106001600160401b038211176114b957604052565b60405190611522826114be565b565b6001600160401b0381116114b957601f01601f191660200190565b92919261154b82611524565b9161155960405193846114f4565b829481845281830111610310578281602093845f960137010152565b60408060031936011261031057600490813561159081610514565b6024356001600160401b0381116103105736602382011215610310576115bf903690602481870135910161153f565b916115c8613b19565b8051926115ff846115f160209363439fab9160e01b858401528460248401526044830190611efb565b03601f1981018652856114f4565b611607613b19565b61160f613a03565b6001600160a01b038381168015929190879084156117c6575b8415611758575b84156116f4575b5050821561165e575b505061164f576100208383614697565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104e9575f926116c7575b5050155f8061163f565b6116e69250803d106116ed575b6116de81836114f4565b81019061264c565b5f806116bd565b503d6116d4565b855163054fd4d560e41b81529294508391839182905afa9081156104e95760029160ff915f9161172b575b5016141591865f611636565b61174b9150843d8611611751575b61174381836114f4565b81019061467e565b5f61171f565b503d611739565b935050835163198ca60560e11b815282818981875afa9081156104e95788917f11a6b7bef0f97d298d56e5af2aa94330353808e861cbac86172faad21b10c505915f916117a9575b5014159361162f565b6117c09150853d87116104e2576104d481836114f4565b5f6117a0565b5f80516020614ded8339815191525490945084906117f4906001600160a01b03165b6001600160a01b031690565b1493611628565b34610310576020366003190112610310576004356001600160a01b0361181f612c60565b163303611855578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b34610310575f366003190112610310577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036118be5760206040515f80516020614ded8339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f366003190112610310576001600160a01b036118eb612af9565b16330361185557005b34610310575f36600319011261031057602060405160018152f35b34610310575f366003190112610310575f80516020614ded833981519152546040516001600160a01b039091168152602090f35b34610310575f36600319011261031057602061050c612c52565b34610310575f366003190112610310576020610de1612c60565b3461031057602036600319011261031057609a80549081905f6004355b8482106119c5575050508110156119ba576104a4905b6040519081529081906020820190565b506104a45f196119aa565b909193808316906001818518811c8301809311611a17575f8790525f80516020614dcd8339815191528301546001600160a01b0316841015611a0c575050935b9190611994565b909591019250611a05565b6125bd565b34610310575f36600319011261031057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104e9576020915f91611a8c575b506040519015158152f35b611aa39150823d84116116ed576116de81836114f4565b5f611a81565b34610310576080366003190112610310576104a4611add600435611acc81610514565b606435906044359060243590612c7f565b604080519384526020840192909252908201529081906060820190565b34610310576040806003193601126103105760043560243591611b1c83610514565b611b24614d5b565b8115611c0d576001600160a01b0383168015611bfc57611b438361261c565b928315611beb57611b52612a9e565b8411611bda57611b89846104a496611b7a610c46611b6f84613369565b60985460801c6125d1565b611b84843361454f565b613d32565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611bcc33614742565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b34610310575f36600319011261031057602061ffff60655460a01c16604051908152f35b34610310576060366003190112610310576104a4611add604435602435600435612cde565b3461031057604080600319360112610310576004359060243590611c8982610514565b611c91613957565b8215611c0d576001600160a01b0382168015611bfc5783611d71611d556104a496611cd3611cc76099546001600160801b031690565b6001600160801b031690565b81611d33611ce883611ce3614bdd565b6126be565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611d2281608081015b03601f1981018352826114f4565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611d4d8382546126a3565b905501613369565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611bc0565b34610310575f36600319011261031057602060d054604051908152f35b34610310575f36600319011261031057602060d154604051908152f35b3461031057611e387f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611e1836610e53565b9290611e22613a03565b6040519182916020835233956020840191612e75565b0390a2005b3461031057602036600319011261031057600435611e5a81610514565b611e62613a03565b6001600160a01b03168015610d9b5760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f84011215610310578235916001600160401b038311610310576020808501948460051b01011161031057565b5f5b838110611eeb5750505f910152565b8181015183820152602001611edc565b90602091611f1481518092818552858086019101611eda565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611f555750505050505090565b9091929394958480611f73600193603f198682030187528a51611efb565b9801930193019194939290611f45565b3461031057602036600319011261031057600480356001600160401b03811161031057611fb4903690600401611eaa565b91611fbe83612eac565b925f5b818110611fd657604051806104a48782611f20565b5f80611fe3838588612f3b565b60409391611ff5855180938193612f5b565b0390305af490612003612f68565b911561202a5750906001916120188288613002565b526120238187613002565b5001611fc1565b848260448151106103105761204e8183612063930151602480918301019101612f97565b925162461bcd60e51b81529283928301612067565b0390fd5b90602061098f928181520190611efb565b34610310575f366003190112610310576104a4604051612097816114be565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611efb565b3461031057604080600319360112610310576004356120db81610514565b6024356001600160a01b03337f00000000000000000000000000000000000000000000000000000000000000008216148015906121db575b6121ca5761211f613957565b612127613978565b8216156121b9578015611beb57917fd083678824038160bef3975359ab29f19c3f0e9bcf9d7ead540a492d4d678b63836121636104a495613e4e565b9361217e610c4661217384613369565b60985460801c612a83565b6121888582613e02565b83516001600160a01b03919091168152602081019190915260408101849052606090a1519081529081906020820190565b825163d92e233d60e01b8152600490fd5b8351634ca8886760e01b8152600490fd5b508351638da5cb5b60e01b81526020816004817f000000000000000000000000000000000000000000000000000000000000000086165afa9081156104e9575f9161222c575b508116301415612113565b61224e915060203d602011612254575b61224681836114f4565b81019061268e565b5f612221565b503d61223c565b3461031057602036600319011261031057602061050c600435613e4e565b34610310575f3660031901126103105760206001600160801b0360995416604051908152f35b34610310576020366003190112610310576100206004356122bf81610514565b6122c7613a03565b613edd565b908160a09103126103105790565b34610310576080366003190112610310576001600160401b036004358181116103105761230b9036906004016122cc565b60243582811161031057612323903690600401611eaa565b6044929192358481116103105761233e903690600401611eaa565b916064359586116103105761235a610020963690600401611eaa565b959094613112565b346103105760203660031901126103105760043561237f81610514565b60018060a01b03165f52609c602052602060405f2054604051908152f35b3461031057604080600319360112610310576004906001600160401b038235818111610310576123d090369085016122cc565b90602435908111610310576123e89036908501611eaa565b9390926123f3613978565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610310575f8251809263837d444160e01b82528183816124428a8a8301613047565b03925af180156104e95761251a575b506801bc16d674ec800000612464612a9e565b1061250d578083019360b06124798686612f09565b9050036124ff576124cb6124cf9160d1549760d054906124be6124b68b6124a08c8c612f09565b611d148b94929451938492602084019687613244565b519020613261565b60208151910120926140cc565b1590565b6124f2576100206001866124ec6124e68888612f09565b90614104565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610d8f612527926114a6565b5f612451565b34610310575f366003190112610310575f546040516001600160a01b039091168152602090f35b604036600319011261031057602061050c60043561257181610514565b6024359061058582610514565b90816020910312610310575190565b6040513d5f823e3d90fd5b906040516125a5816114be565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211611a1757565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b038116908161263457505090565b9161098f9260801c90613439565b8015150361031057565b90816020910312610310575161098f81612642565b90816020910312610310575161098f81610334565b81810392915f138015828513169184121617611a1757565b90816020910312610310575161098f81610514565b91908203918211611a1757565b9060018201809211611a1757565b91908201809211611a1757565b600160ff1b8114611a17575f0390565b9190915f8382019384129112908015821691151617611a1757565b60408051630156a69560e11b8152306004808301919091526001600160a01b039390926020929183836024817f00000000000000000000000000000000000000000000000000000000000000008a165afa9283156104e9575f93612a60575b5061275f90613586565b9590809315612940575b507f0000000000000000000000000000000000000000000000000000000000000000169281516278744560e21b815281818781885afa9081156104e9575f91612923575b508251631cd5ec3960e31b81529082828881895afa9182156104e9576127db935f93612904575b50506126a3565b6127ee81611ce3611cc760985460801c90565b905f841215612897576128129161280d91612808866126cb565b613439565b61370b565b9261281c846126cb565b90803b1561031057915163304f0a6b60e21b81529485019081525f91859182908490829060200103925af19283156104e95761285d93612884575b506126db565b80612875575b5061286a57565b61287261382e565b50565b61287e90613734565b5f612863565b80610d8f612891926114a6565b5f612857565b6128a99161280d918597949697613439565b92843b15610310575163304f0a6b60e21b815290810183815290935f9185919082908490829060200103925af19283156104e9576128ec936128f1575b50612676565b61285d565b80610d8f6128fe926114a6565b5f6128e6565b61291b929350803d106104e2576104d481836114f4565b905f806127d4565b61293a9150823d84116104e2576104d481836114f4565b5f6127ad565b825163070aab0d60e11b8152919350848287817f000000000000000000000000000000000000000000000000000000000000000088165afa80156104e9576001600160801b0361299c916129a2945f91612a33575b501661370b565b90612676565b918151638da5cb5b60e01b815284818781857f0000000000000000000000000000000000000000000000000000000000000000165afa9081156104e9575f91612a16575b5081163014801590612a0d575b6129fd575f612769565b815163c284f82560e01b81528590fd5b505f83126129f3565b612a2d9150853d87116122545761224681836114f4565b5f6129e6565b612a539150883d8a11612a59575b612a4b81836114f4565b810190612661565b5f612995565b503d612a41565b61275f919350612a7c90853d87116116ed576116de81836114f4565b9290612755565b9190916001600160801b0380809416911601918211611a1757565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316314701609954612ae06001600160801b03821661261c565b9060801c01908181115f14612af3570390565b50505f90565b61016a546001600160a01b03168015612b0f5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b9061098f949360809361ffff9260018060a01b0316845260208401521660408201528160608201520190611efb565b9081019060408183031261031057803590612b7d82610514565b60208101356001600160401b03918282116103105701916060838503126103105760405191612bab836114d9565b8335835260208401359361ffff851685036103105760208401948552604081013591821161031057019084601f8301121561031057612c3e612c177f6efc3c5ea2064c46840711aa5ff8d7f70826faa0cc04fcf0557a3863533aafad96846020612c4d9635910161153f565b604085019081526001600160a01b0390921693612c348186613a3d565b51945161ffff1690565b90519060405194859485612b34565b0390a1565b609d548061098f57505f1990565b60d2546001600160a01b0390811680612c7a57505f541690565b905090565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612ccf929091612cb88160808101611d14565b5190205f52609b60205260405f2054928391613b97565b9091828103908111611a175792565b929190915f93612d0e7f0000000000000000000000000000000000000000000000000000000000000000856126be565b4210612e4b5760408051336020820190815291810186905260608082018490528152601f1991612d4f91612d436080826114f4565b51902094868433612c7f565b9096909587878115612e3d5750505f908152609b602052604081205560018211612df3575b505050612dac612d91612d8685613369565b60995460801c6125d1565b6001600160801b036099549181199060801b16911617609955565b612db68333613d32565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b612e3491929750612e0487856126be565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611d2290826114f4565b555f8080612d74565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116114b95760051b60200190565b90612eb682612e95565b612ec360405191826114f4565b8281528092612ed4601f1991612e95565b01905f5b828110612ee457505050565b806060602080938501015201612ed8565b634e487b7160e01b5f52603260045260245ffd5b903590601e198136030182121561031057018035906001600160401b0382116103105760200191813603831361031057565b90821015612f5657612f529160051b810190612f09565b9091565b612ef5565b908092918237015f815290565b3d15612f92573d90612f7982611524565b91612f8760405193846114f4565b82523d5f602084013e565b606090565b602081830312610310578051906001600160401b038211610310570181601f82011215610310578051612fc981611524565b92612fd760405194856114f4565b818452602082840101116103105761098f9160208085019101611eda565b805115612f565760200190565b8051821015612f565760209160051b010190565b9035601e19823603018112156103105701602081359101916001600160401b03821161031057813603831361031057565b9060a061098f926020815282356020820152602083013560408201526130836130736040850185613016565b84606085015260c0840191612e75565b906130b66130ab6130976060870187613016565b601f19858703810160808701529591612e75565b946080810190613016565b93909282860301910152612e75565b906801bc16d674ec8000009180830292830403611a1757565b90670de0b6b3a764000091828102928184041490151715611a1757565b9061271091828102928184041490151715611a1757565b929094939195613120613978565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b15610310576040965f8851809263837d444160e01b82528183816131748c60048301613047565b03925af180156104e957613231575b5061318c612a9e565b613195896130c5565b116132205787158015613206575b6131f557916131d39593916131cd896124cb97956131c760d054978c810190612f09565b90613f3f565b946140ba565b6131e557506115229060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061321387860186612f09565b905060b0890214156131a3565b86516396d8043360e01b8152600490fd5b80610d8f61323e926114a6565b5f613183565b93929160209161325c91604087526040870191612e75565b930152565b9060405191602083015260208252611522826114be565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036132aa57565b612872343361421f565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f9161334a575b5060208201916001600160801b03918284511691828214613343578361333661333161333e958584865116613439565b613369565b169052613369565b169052565b5050505050565b613363915060203d6020116104e2576104d481836114f4565b5f613301565b6001600160801b039081811161337d571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156133ba570490565b61339c565b90808202905f198184099082808310920391808303921461342e57612710908282111561341c577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146134ac578483111561341c57829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061098f92506133b0565b90816060910312610310578051916040602083015192015161098f81612642565b81835290916001600160fb1b0383116103105760209260051b809284830137010190565b90602082528035602083015260208101358060130b809103610310576040830152604081013561352d81610514565b6001600160a01b031660608381019190915281013536829003601e19018112156103105701602081359101906001600160401b038111610310578060051b360382136103105760a08360808061098f96015201916134da565b6040516325f56f1160e01b81526001600160a01b039291606090829081906135b190600483016134fe565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104e9575f915f905f956136d6575b50841561368357816135fb612af9565b16917f000000000000000000000000000000000000000000000000000000000000000016821461367c57509060205f92600460405180958193634641257d60e01b83525af19081156104e957613657925f9261365b57506126db565b9190565b61367591925060203d6020116104e2576104d481836114f4565b905f612857565b9081613689575b50509190565b803b1561031057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104e9576136c3575b80613683565b80610d8f6136d0926114a6565b5f6136bd565b919450506136fc915060603d606011613704575b6136f481836114f4565b8101906134b9565b93905f6135eb565b503d6136ea565b6001600160ff1b03811161371c5790565b6024906040519063123baf0360e11b82526004820152fd5b613743611cc760985460801c90565b5f82126138155781613754916126be565b90613761610c4683613369565b6137766065549161ffff8360a01c16906133bf565b801561381057807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc35318686547936137b4611cc76098546001600160801b031690565b806137fa575050612c4d90925b6001600160a01b0316916137d58484613e02565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b612c4d9261380a92039084613439565b926137c1565b505050565b613331610c4691613828611522946126cb565b906126a3565b609954906001600160801b0382169182156139515760801c61388e61387f827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163147016126a3565b6138888561261c565b90614393565b90811561394a5761389e82613e4e565b93841561394257826138ca612d9161333161152296610c4696611ce3611d556133318d611b6f9a6126a3565b6138d481876143f9565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a161333161392661391588613369565b6098546001600160801b03166125d1565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b61395f6144e0565b1561396657565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f916139e4575b506139d257565b60405163e775715160e01b8152600490fd5b6139fd915060203d6020116116ed576116de81836114f4565b5f6139cb565b5f546001600160a01b0316330361185557565b908160a0910312610310578051916020820151916040810151916080606083015192015190565b90613a4661459c565b6040810151613a5361459c565b5f80546001600160a01b0319166001600160a01b03851617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190613aa19082612067565b0390a26020810151613ab161459c565b61271061ffff821611613b0757613aca613aef93613edd565b6065805461ffff60a01b191660a09290921b61ffff60a01b16919091179055516145ca565b613af76145fa565b613aff61459c565b61152261461b565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613b57575b50506118be57565b5f80516020614ded8339815191525416141590505f80613b4f565b90604051613b7f816114be565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613d2a575b613d1d5783613ce7575f5b609a5f526001600160a01b0316613bdc5f80516020614dcd8339815191528601613b72565b8051909790613bf3906001600160a01b03166117e8565b98613c18613c0c6020809b01516001600160601b031690565b6001600160601b031690565b948381108015613cdd575b613ccb5791600193979a95613c42613c4e939488035b838c0390614393565b80920198870391613439565b01970193808611801590613cc1575b613cb657609a5f528290613c7f5f80516020614dcd8339815191528701613b72565b805190890151969992966001600160a01b039091169460019392613c4e9290916001600160601b0390911690613c42908803613c39565b945050509250509190565b5081851015613c5d565b60405163e8722f8f60e01b8152600490fd5b50808b1115613c23565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b0316613bb7565b505093505050505f905f90565b508415613bac565b478211613df5575b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006002815414613de35760029055814710613dcb575f918291829182916001600160a01b03165af1613d8a612f68565b5015613db95761152260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b613dfd6148db565b613d3a565b613e0b82613369565b60985490613e236001600160801b0391828416612a83565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b609854906001600160801b03821681158015613e7d575b15613e705750905090565b61098f9260801c91613439565b508015613e65565b6098546001600160801b0381169082158015613ed5575b15613ea657505090565b60801c90613eb5828285613439565b9282156133ba5709613ec45790565b600181018091111561098f576125bd565b508115613e9c565b613ee5613978565b6001600160a01b03168015613f2d57606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b919290613f4a6148db565b60d154925f925f90613f5b81614952565b96613f64614cf4565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a10613fa6575050505050505050505090565b60b0613fb69101809989856149b4565b9960409a8c613ff28d51613fda602091828101906124b681611d148c8a8d87613244565b805191012091613feb858b8b6149d5565b3590613002565b52613ffd8184614984565b909361401d61401761400f8584614992565b9590936149a3565b906149e5565b908a3b15610310578b8f5f93614048915196879485946304512a2360e31b8652888c60048801614a01565b03816801bc16d674ec8000008d5af19384156104e95761409b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19582986140a7575b5097019e5192839283614a4f565b0390a101989097613f92565b80610d8f6140b4926114a6565b5f61408d565b906140c89495939291614a78565b1490565b9192915f915b8083106140e0575050501490565b9091926140fb6001916140f48685876149d5565b3590614d1d565b930191906140d2565b61410c6148db565b8160301161031057614017917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661414a614cf4565b906141616141588486614992565b969094866149a3565b94813b15610310576801bc16d674ec8000005f946141c797604051988996879586946304512a2360e31b8652608060048701526141b86141a58d6084890190612e5d565b60031994858983030160248a0152611efb565b92868403016044870152612e75565b90606483015203925af19081156104e9577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb192612c4d92614210575b5060405191829182614a3e565b614219906114a6565b5f614203565b9190614229613978565b6001600160a01b038316908115610d9b5780156142d55780614250611cc760985460801c90565b019361425a612c52565b85116142c357610c46946142819161427c61427485613e85565b978893613369565b613e02565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b909291926142f3613978565b6001600160a01b038216918215610d9b5781156142d5578161431a611cc760985460801c90565b01614323612c52565b81116142c357610c469561436a6142be927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9461427c61436288613e85565b9a8b93613369565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b9080821015612c7a575090565b609a5490600160401b8210156114b9576001820180609a55821015612f5657609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f80516020614dcd83398151915290910155565b90811580156144d8575b6144c657609a548061449057505f905b6001600160a01b03918216928301928310611a175781831161447057611522929161445b61444361446b93614c1f565b9161444c611515565b94166001600160a01b03168452565b6001600160601b03166020830152565b6143a0565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031690614413565b604051632ec8835b60e21b8152600490fd5b508015614403565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f91614536575090565b61098f915060203d6020116116ed576116de81836114f4565b60018060a01b03165f52609c60205260405f20908154818103908111611a17576145799255613369565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f80516020614e0d8339815191525460401c16156145b857565b604051631afcd79f60e31b8152600490fd5b6145d261459c565b80156145e857600181016145e35750565b609d55565b6040516331278a8760e01b8152600490fd5b61460261459c565b6801bc16d674ec800000614614612c52565b106145e857565b61462361459c565b61462b61459c565b61463361459c565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca00341061466c57612872343061421f565b60405163ea2559bb60e01b8152600490fd5b90816020910312610310575160ff811681036103105790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614721575b506146e757604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f80516020614ded833981519152840361470857611522929350614c52565b604051632a87526960e21b815260048101859052602490fd5b61473b91955060203d6020116104e2576104d481836114f4565b935f6146c1565b6001600160a01b0381165f9081526101376020526040902061476390612598565b906001600160801b0361477d83516001600160801b031690565b16156148d7576106f26147b491614792613978565b61479b846132b4565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104e957614817869361482592614851965f926148bf57506133bf565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104e9575f936148a0575b50501061488e57565b604051633684c65960e01b8152600490fd5b6148b7929350803d106104e2576104d481836114f4565b905f80614885565b610864919250863d88116104e2576104d481836114f4565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803180614910575050565b813b15610310575f9160448392604051948593849263f3fef3a360e01b845230600485015260248401525af180156104e9576149495750565b611522906114a6565b9061495c82612e95565b61496960405191826114f4565b828152809261497a601f1991612e95565b0190602036910137565b906030116103105790603090565b906090116103105760300190606090565b9060b0116103105760900190602090565b90939293848311610310578411610310578101920390565b9015612f565790565b9190811015612f565760051b0190565b3590602081106149f3575090565b5f199060200360031b1b1690565b9695949061325c93614a22614a30926060979560808c5260808c0191612e75565b9089820360208b0152611efb565b918783036040890152612e75565b90602061098f928181520190612e5d565b91602061098f938181520191612e75565b5f198114611a175760010190565b3561098f81612642565b9293919091805193614a8a84866126be565b614a93876126b0565b03614ad557614aa186614952565b945f8094885f965f5b828110614b0d575050159150614ae790505750505003614ad557614ad1915f190190613002565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614aff575050614ad190612ff5565b614b0992506149cc565b3590565b8a86861015614bc05750614b3f614b3a82614b31614b2a89614a60565b988c613002565b51955b876149d5565b614a6e565b15614ba5578a86861015614b845750614b7060019293614b68614b6188614a60565b978b613002565b515b90614d1d565b614b7a828d613002565b5201908a91614aaa565b92614b7090614b9f84614b9960019691614a60565b96613002565b51614b6a565b614b70600192936140f4614bb88c614a60565b9b8d8b6149d5565b91614b3a82614bd683614b99614b3f9591614a60565b5195614b34565b609a5480614bea57505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b03166117e8565b6001600160601b0390818111614c33571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b15614cd3575f80516020614ded83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2805115614cb85761287291614d3e565b505034614cc157565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b604051600160f81b60208201525f60218201523060601b602c8201526020815261098f816114be565b81811015614d31575f5260205260405f2090565b905f5260205260405f2090565b5f8061098f93602081519101845af4614d55612f68565b91614d7b565b614d636144e0565b614d6957565b6040516389a1dc6360e01b8152600490fd5b90614d905750805115613db957805190602001fd5b81511580614dc3575b614da1575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15614d9956fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122008c0a365c0eacebc60ec435e202f7516e2d88ee6141f2dc09523f89e64d7345864736f6c63430008160033", + "deployedBytecode": "0x60806040526004361015610022575b3615610018575f80fd5b610020613278565b005b5f3560e01c806301e1d11414610301578063066055e0146102fc57806307a2d13a146102f757806318f72950146102f25780631a7ff553146102ed578063201b9eb5146102e857806323d18ed8146102e35780632999ad3f146102de5780632cdf7401146102d95780633229fa95146102d457806333194c0a146102cf5780633a98ef39146102ca578063439fab91146102c557806343e82a79146102c057806346904840146102bb5780634ec96b22146102b65780634f1ef286146102b1578063514e2708146102ac57806352d1902d146102a757806353156f28146102a257806354fd4d501461029d5780635c60da1b146102985780635cfc1a51146102935780635dddf3a81461028e57806360d60e6e1461028957806372b410a81461028457806376b58b901461027f5780637bde82f21461027a5780637fd6f15c146102755780638697d2c2146102705780638ceab9aa1461026b5780639b401cde14610266578063a1bf49aa14610261578063a49a1e7d1461025c578063aaa4e83614610257578063ac9650d814610252578063ad3cb1cc1461024d578063ad68ebf714610248578063c6e6f59214610243578063d83ad00c1461023e578063e74b981b14610239578063ef2a215814610234578063f04da65b1461022f578063f5e9de4d1461022a578063f851a440146102255763f9609f080361000e57612554565b61252d565b61239d565b612362565b6122da565b61229f565b612279565b61225b565b6120bd565b612078565b611f83565b611e3d565b611de6565b611dc9565b611dac565b611c66565b611c41565b611c1d565b611afa565b611aa9565b611a1c565b611977565b61195d565b611943565b61190f565b6118f4565b6118d0565b611867565b6117fb565b611575565b61141c565b6113f4565b610fb5565b610e9c565b610e2d565b610df3565b610dc7565b610dad565b610992565b6108ec565b6105bf565b61058c565b610533565b6104ee565b610345565b610314565b5f91031261031057565b5f80fd5b34610310575f36600319011261031057602060985460801c604051908152f35b6001600160801b0381160361031057565b346103105760203660031901126103105760043561036281610334565b604051633b9e9f0160e21b81523360048201526001600160801b03821660248201526020816044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19081156104e9575f916104ba575b50335f908152610137602052604090206103de90612598565b916001600160801b03806103f985516001600160801b031690565b16156104a8578361043d610430610420610456946104196104a4996132b4565b8616613369565b83516001600160801b03166125d1565b6001600160801b03168252565b335f908152610137602052604090206125ea565b6125ea565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104dc915060203d6020116104e2575b6104d481836114f4565b81019061257e565b5f6103c5565b503d6104ca565b61258d565b3461031057602036600319011261031057602061050c60043561261c565b604051908152f35b6001600160a01b0381160361031057565b908160809103126103105790565b60603660031901126103105760043561054b81610514565b60243561055781610514565b604435906001600160401b0382116103105760209261058561058061050c943690600401610525565b6126f6565b34906142e7565b34610310576020366003190112610310576004356001600160401b03811161031057610580610020913690600401610525565b346103105760603660031901126103105760048035906105de82610514565b60243590604435926105ef84610514565b6105f7613957565b6105ff613978565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104e9575f986108cd575b50335f90815261013760205260409020839061068890612598565b946001600160801b036106a287516001600160801b031690565b161561086b576106b1866132b4565b6106dd6106d06106c089613369565b88516001600160801b0316612a83565b6001600160801b03168752565b335f908152609c6020526040902084906106f8905b5461261c565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104e95761078792859261074b925f9261084c575b506133bf565b9261075d87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104e9575f9361082d575b50501061081f5750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916107e66104a4976104513360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610844929350803d106104e2576104d481836114f4565b905f80610799565b610864919250843d86116104e2576104d481836114f4565b905f610745565b885163752a536d60e01b8152915083828681865afa80156104e95761089c6108ab9187945f916108b0575b50613369565b6001600160801b031687860152565b6106b1565b6108c79150873d89116104e2576104d481836114f4565b5f610896565b6108e5919850823d84116104e2576104d481836114f4565b965f61066d565b34610310575f8060031936011261031057610905613a03565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610310575f809160046040518094819363b4b6d74f60e01b83525af180156104e95761095c575080f35b61002091506114a6565b6060906003190112610310576004359060243561098281610514565b9060443561098f81610514565b90565b34610310576109a036610966565b906001600160a01b0380831615610d9b576109b9613978565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103105760408051631d8557d760e01b815260049491905f81878183875af180156104e957610d82575b506001600160a01b0383165f90815261013760205260409020610a2c90612598565b6001600160801b03610a4582516001600160801b031690565b1615610d7257610a54816132b4565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104e957610ac3975f955f91610d39575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104e957610ade925f91610d1c57506133bf565b95610afc6106f28960018060a01b03165f52609c60205260405f2090565b918288118015610d0c575b610cfc57908a610b4492610b2288516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104e957670de0b6b3a764000093610b80938d5f94610cd3575b5050610b74610b7a916130de565b926130fb565b91613439565b1015610cc5578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104e9577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610ca295610c1a93610ca7575b5050610bfd6104306104208c613369565b6001600160a01b0386165f908152610137602052604090206125ea565b610c2382613e4e565b90610c61610c46610c3385613369565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610c6b828661454f565b610c758389613d32565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610cbd92903d106104e2576104d481836114f4565b505f80610bec565b835163185cfc6d60e11b8152fd5b610b7a929450610b749181610cf392903d106104e2576104d481836114f4565b9391508d610b66565b865163efda1a2760e01b81528490fd5b50610d15612a9e565b8811610b07565b610d3391508c8d3d106104e2576104d481836114f4565b5f610745565b9050610d5e91955060a03d60a011610d6b575b610d5681836114f4565b810190613a16565b509692509050945f610a9f565b503d610d4c565b815163673f032f60e11b81528690fd5b80610d8f610d95926114a6565b80610306565b5f610a0a565b60405163d92e233d60e01b8152600490fd5b34610310575f36600319011261031057602061050c612a9e565b34610310575f366003190112610310576020610de1612af9565b6040516001600160a01b039091168152f35b34610310575f3660031901126103105760206040517f11a6b7bef0f97d298d56e5af2aa94330353808e861cbac86172faad21b10c5058152f35b34610310575f3660031901126103105760206001600160801b0360985416604051908152f35b906020600319830112610310576004356001600160401b039283821161031057806023830112156103105781600401359384116103105760248483010111610310576024019190565b610ea536610e53565b905f80516020614e0d83398151915254916001600160401b0360ff8460401c1615931680159081610fad575b6001149081610fa3575b159081610f9a575b50610f88575f80516020614e0d833981519152805467ffffffffffffffff19166001179055610f169183610f6457612b63565b610f1c57005b5f80516020614e0d833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020614e0d833981519152805460ff60401b1916600160401b179055612b63565b60405163f92ee8a960e01b8152600490fd5b9050155f610ee3565b303b159150610edb565b849150610ed1565b3461031057610fc336610966565b906001600160a01b039081831615610d9b57610fdd613978565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103105760408051631d8557d760e01b815260049291905f81858183875af180156104e9576113e1575b506001600160a01b0384165f9081526101376020526040902061104f90612598565b926001600160801b0361106985516001600160801b031690565b16156113d357611078846132b4565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104e9575f955f956113a5575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104e9575f99611386575b506001600160a01b038a165f908152609c60205260409020611117906106f2565b90818a118015611376575b6113665761115d908661113c87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104e9575f92611345575b5061117b91926133bf565b11611335578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104e9578592611318575b506111c48d613369565b84516001600160801b0316906111d9916125d1565b6001600160801b031684526001600160a01b038a165f9081526101376020526040902084611206916125ea565b61120f89613e4e565b976112198a613369565b60985460801c036001600160801b0316611248906001600160801b036098549181199060801b16911617609855565b611252898c61454f565b6001600160a01b038b165f908152609c60205260409020546112739061261c565b9061127d916133bf565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104e9575f936112f9575b5050116112eb575091610ca2917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610c758389613d32565b9051631d8fa13d60e31b8152fd5b611310929350803d106104e2576104d481836114f4565b905f806112b0565b61132e90833d85116104e2576104d481836114f4565b505f6111ba565b855163324b20e160e11b81528590fd5b61117b925061136090883d8a116104e2576104d481836114f4565b91611170565b875163efda1a2760e01b81528790fd5b5061137f612a9e565b8a11611122565b61139e919950853d87116104e2576104d481836114f4565b975f6110f6565b6110e39296506113c591955060a03d60a011610d6b57610d5681836114f4565b5050509590959490916110bf565b905163673f032f60e11b8152fd5b80610d8f6113ee926114a6565b5f61102d565b34610310575f366003190112610310576065546040516001600160a01b039091168152602090f35b346103105760203660031901126103105760043561143981610514565b60018060a01b03165f52610137602052602060405f206040519061145c826114be565b54906001600160801b03918281169081835260801c84830152611484575b5116604051908152f35b61148d816132b4565b61147a565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116114b957604052565b611492565b604081019081106001600160401b038211176114b957604052565b606081019081106001600160401b038211176114b957604052565b90601f801991011681019081106001600160401b038211176114b957604052565b60405190611522826114be565b565b6001600160401b0381116114b957601f01601f191660200190565b92919261154b82611524565b9161155960405193846114f4565b829481845281830111610310578281602093845f960137010152565b60408060031936011261031057600490813561159081610514565b6024356001600160401b0381116103105736602382011215610310576115bf903690602481870135910161153f565b916115c8613b19565b8051926115ff846115f160209363439fab9160e01b858401528460248401526044830190611efb565b03601f1981018652856114f4565b611607613b19565b61160f613a03565b6001600160a01b038381168015929190879084156117c6575b8415611758575b84156116f4575b5050821561165e575b505061164f576100208383614697565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104e9575f926116c7575b5050155f8061163f565b6116e69250803d106116ed575b6116de81836114f4565b81019061264c565b5f806116bd565b503d6116d4565b855163054fd4d560e41b81529294508391839182905afa9081156104e95760029160ff915f9161172b575b5016141591865f611636565b61174b9150843d8611611751575b61174381836114f4565b81019061467e565b5f61171f565b503d611739565b935050835163198ca60560e11b815282818981875afa9081156104e95788917f11a6b7bef0f97d298d56e5af2aa94330353808e861cbac86172faad21b10c505915f916117a9575b5014159361162f565b6117c09150853d87116104e2576104d481836114f4565b5f6117a0565b5f80516020614ded8339815191525490945084906117f4906001600160a01b03165b6001600160a01b031690565b1493611628565b34610310576020366003190112610310576004356001600160a01b0361181f612c60565b163303611855578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b34610310575f366003190112610310577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036118be5760206040515f80516020614ded8339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f366003190112610310576001600160a01b036118eb612af9565b16330361185557005b34610310575f36600319011261031057602060405160018152f35b34610310575f366003190112610310575f80516020614ded833981519152546040516001600160a01b039091168152602090f35b34610310575f36600319011261031057602061050c612c52565b34610310575f366003190112610310576020610de1612c60565b3461031057602036600319011261031057609a80549081905f6004355b8482106119c5575050508110156119ba576104a4905b6040519081529081906020820190565b506104a45f196119aa565b909193808316906001818518811c8301809311611a17575f8790525f80516020614dcd8339815191528301546001600160a01b0316841015611a0c575050935b9190611994565b909591019250611a05565b6125bd565b34610310575f36600319011261031057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104e9576020915f91611a8c575b506040519015158152f35b611aa39150823d84116116ed576116de81836114f4565b5f611a81565b34610310576080366003190112610310576104a4611add600435611acc81610514565b606435906044359060243590612c7f565b604080519384526020840192909252908201529081906060820190565b34610310576040806003193601126103105760043560243591611b1c83610514565b611b24614d5b565b8115611c0d576001600160a01b0383168015611bfc57611b438361261c565b928315611beb57611b52612a9e565b8411611bda57611b89846104a496611b7a610c46611b6f84613369565b60985460801c6125d1565b611b84843361454f565b613d32565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611bcc33614742565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b34610310575f36600319011261031057602061ffff60655460a01c16604051908152f35b34610310576060366003190112610310576104a4611add604435602435600435612cde565b3461031057604080600319360112610310576004359060243590611c8982610514565b611c91613957565b8215611c0d576001600160a01b0382168015611bfc5783611d71611d556104a496611cd3611cc76099546001600160801b031690565b6001600160801b031690565b81611d33611ce883611ce3614bdd565b6126be565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611d2281608081015b03601f1981018352826114f4565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611d4d8382546126a3565b905501613369565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611bc0565b34610310575f36600319011261031057602060d054604051908152f35b34610310575f36600319011261031057602060d154604051908152f35b3461031057611e387f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611e1836610e53565b9290611e22613a03565b6040519182916020835233956020840191612e75565b0390a2005b3461031057602036600319011261031057600435611e5a81610514565b611e62613a03565b6001600160a01b03168015610d9b5760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f84011215610310578235916001600160401b038311610310576020808501948460051b01011161031057565b5f5b838110611eeb5750505f910152565b8181015183820152602001611edc565b90602091611f1481518092818552858086019101611eda565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611f555750505050505090565b9091929394958480611f73600193603f198682030187528a51611efb565b9801930193019194939290611f45565b3461031057602036600319011261031057600480356001600160401b03811161031057611fb4903690600401611eaa565b91611fbe83612eac565b925f5b818110611fd657604051806104a48782611f20565b5f80611fe3838588612f3b565b60409391611ff5855180938193612f5b565b0390305af490612003612f68565b911561202a5750906001916120188288613002565b526120238187613002565b5001611fc1565b848260448151106103105761204e8183612063930151602480918301019101612f97565b925162461bcd60e51b81529283928301612067565b0390fd5b90602061098f928181520190611efb565b34610310575f366003190112610310576104a4604051612097816114be565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611efb565b3461031057604080600319360112610310576004356120db81610514565b6024356001600160a01b03337f00000000000000000000000000000000000000000000000000000000000000008216148015906121db575b6121ca5761211f613957565b612127613978565b8216156121b9578015611beb57917fd083678824038160bef3975359ab29f19c3f0e9bcf9d7ead540a492d4d678b63836121636104a495613e4e565b9361217e610c4661217384613369565b60985460801c612a83565b6121888582613e02565b83516001600160a01b03919091168152602081019190915260408101849052606090a1519081529081906020820190565b825163d92e233d60e01b8152600490fd5b8351634ca8886760e01b8152600490fd5b508351638da5cb5b60e01b81526020816004817f000000000000000000000000000000000000000000000000000000000000000086165afa9081156104e9575f9161222c575b508116301415612113565b61224e915060203d602011612254575b61224681836114f4565b81019061268e565b5f612221565b503d61223c565b3461031057602036600319011261031057602061050c600435613e4e565b34610310575f3660031901126103105760206001600160801b0360995416604051908152f35b34610310576020366003190112610310576100206004356122bf81610514565b6122c7613a03565b613edd565b908160a09103126103105790565b34610310576080366003190112610310576001600160401b036004358181116103105761230b9036906004016122cc565b60243582811161031057612323903690600401611eaa565b6044929192358481116103105761233e903690600401611eaa565b916064359586116103105761235a610020963690600401611eaa565b959094613112565b346103105760203660031901126103105760043561237f81610514565b60018060a01b03165f52609c602052602060405f2054604051908152f35b3461031057604080600319360112610310576004906001600160401b038235818111610310576123d090369085016122cc565b90602435908111610310576123e89036908501611eaa565b9390926123f3613978565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610310575f8251809263837d444160e01b82528183816124428a8a8301613047565b03925af180156104e95761251a575b506801bc16d674ec800000612464612a9e565b1061250d578083019360b06124798686612f09565b9050036124ff576124cb6124cf9160d1549760d054906124be6124b68b6124a08c8c612f09565b611d148b94929451938492602084019687613244565b519020613261565b60208151910120926140cc565b1590565b6124f2576100206001866124ec6124e68888612f09565b90614104565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610d8f612527926114a6565b5f612451565b34610310575f366003190112610310575f546040516001600160a01b039091168152602090f35b604036600319011261031057602061050c60043561257181610514565b6024359061058582610514565b90816020910312610310575190565b6040513d5f823e3d90fd5b906040516125a5816114be565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211611a1757565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b038116908161263457505090565b9161098f9260801c90613439565b8015150361031057565b90816020910312610310575161098f81612642565b90816020910312610310575161098f81610334565b81810392915f138015828513169184121617611a1757565b90816020910312610310575161098f81610514565b91908203918211611a1757565b9060018201809211611a1757565b91908201809211611a1757565b600160ff1b8114611a17575f0390565b9190915f8382019384129112908015821691151617611a1757565b60408051630156a69560e11b8152306004808301919091526001600160a01b039390926020929183836024817f00000000000000000000000000000000000000000000000000000000000000008a165afa9283156104e9575f93612a60575b5061275f90613586565b9590809315612940575b507f0000000000000000000000000000000000000000000000000000000000000000169281516278744560e21b815281818781885afa9081156104e9575f91612923575b508251631cd5ec3960e31b81529082828881895afa9182156104e9576127db935f93612904575b50506126a3565b6127ee81611ce3611cc760985460801c90565b905f841215612897576128129161280d91612808866126cb565b613439565b61370b565b9261281c846126cb565b90803b1561031057915163304f0a6b60e21b81529485019081525f91859182908490829060200103925af19283156104e95761285d93612884575b506126db565b80612875575b5061286a57565b61287261382e565b50565b61287e90613734565b5f612863565b80610d8f612891926114a6565b5f612857565b6128a99161280d918597949697613439565b92843b15610310575163304f0a6b60e21b815290810183815290935f9185919082908490829060200103925af19283156104e9576128ec936128f1575b50612676565b61285d565b80610d8f6128fe926114a6565b5f6128e6565b61291b929350803d106104e2576104d481836114f4565b905f806127d4565b61293a9150823d84116104e2576104d481836114f4565b5f6127ad565b825163070aab0d60e11b8152919350848287817f000000000000000000000000000000000000000000000000000000000000000088165afa80156104e9576001600160801b0361299c916129a2945f91612a33575b501661370b565b90612676565b918151638da5cb5b60e01b815284818781857f0000000000000000000000000000000000000000000000000000000000000000165afa9081156104e9575f91612a16575b5081163014801590612a0d575b6129fd575f612769565b815163c284f82560e01b81528590fd5b505f83126129f3565b612a2d9150853d87116122545761224681836114f4565b5f6129e6565b612a539150883d8a11612a59575b612a4b81836114f4565b810190612661565b5f612995565b503d612a41565b61275f919350612a7c90853d87116116ed576116de81836114f4565b9290612755565b9190916001600160801b0380809416911601918211611a1757565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316314701609954612ae06001600160801b03821661261c565b9060801c01908181115f14612af3570390565b50505f90565b61016a546001600160a01b03168015612b0f5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b9061098f949360809361ffff9260018060a01b0316845260208401521660408201528160608201520190611efb565b9081019060408183031261031057803590612b7d82610514565b60208101356001600160401b03918282116103105701916060838503126103105760405191612bab836114d9565b8335835260208401359361ffff851685036103105760208401948552604081013591821161031057019084601f8301121561031057612c3e612c177f6efc3c5ea2064c46840711aa5ff8d7f70826faa0cc04fcf0557a3863533aafad96846020612c4d9635910161153f565b604085019081526001600160a01b0390921693612c348186613a3d565b51945161ffff1690565b90519060405194859485612b34565b0390a1565b609d548061098f57505f1990565b60d2546001600160a01b0390811680612c7a57505f541690565b905090565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612ccf929091612cb88160808101611d14565b5190205f52609b60205260405f2054928391613b97565b9091828103908111611a175792565b929190915f93612d0e7f0000000000000000000000000000000000000000000000000000000000000000856126be565b4210612e4b5760408051336020820190815291810186905260608082018490528152601f1991612d4f91612d436080826114f4565b51902094868433612c7f565b9096909587878115612e3d5750505f908152609b602052604081205560018211612df3575b505050612dac612d91612d8685613369565b60995460801c6125d1565b6001600160801b036099549181199060801b16911617609955565b612db68333613d32565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b612e3491929750612e0487856126be565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611d2290826114f4565b555f8080612d74565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116114b95760051b60200190565b90612eb682612e95565b612ec360405191826114f4565b8281528092612ed4601f1991612e95565b01905f5b828110612ee457505050565b806060602080938501015201612ed8565b634e487b7160e01b5f52603260045260245ffd5b903590601e198136030182121561031057018035906001600160401b0382116103105760200191813603831361031057565b90821015612f5657612f529160051b810190612f09565b9091565b612ef5565b908092918237015f815290565b3d15612f92573d90612f7982611524565b91612f8760405193846114f4565b82523d5f602084013e565b606090565b602081830312610310578051906001600160401b038211610310570181601f82011215610310578051612fc981611524565b92612fd760405194856114f4565b818452602082840101116103105761098f9160208085019101611eda565b805115612f565760200190565b8051821015612f565760209160051b010190565b9035601e19823603018112156103105701602081359101916001600160401b03821161031057813603831361031057565b9060a061098f926020815282356020820152602083013560408201526130836130736040850185613016565b84606085015260c0840191612e75565b906130b66130ab6130976060870187613016565b601f19858703810160808701529591612e75565b946080810190613016565b93909282860301910152612e75565b906801bc16d674ec8000009180830292830403611a1757565b90670de0b6b3a764000091828102928184041490151715611a1757565b9061271091828102928184041490151715611a1757565b929094939195613120613978565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b15610310576040965f8851809263837d444160e01b82528183816131748c60048301613047565b03925af180156104e957613231575b5061318c612a9e565b613195896130c5565b116132205787158015613206575b6131f557916131d39593916131cd896124cb97956131c760d054978c810190612f09565b90613f3f565b946140ba565b6131e557506115229060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061321387860186612f09565b905060b0890214156131a3565b86516396d8043360e01b8152600490fd5b80610d8f61323e926114a6565b5f613183565b93929160209161325c91604087526040870191612e75565b930152565b9060405191602083015260208252611522826114be565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036132aa57565b612872343361421f565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f9161334a575b5060208201916001600160801b03918284511691828214613343578361333661333161333e958584865116613439565b613369565b169052613369565b169052565b5050505050565b613363915060203d6020116104e2576104d481836114f4565b5f613301565b6001600160801b039081811161337d571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156133ba570490565b61339c565b90808202905f198184099082808310920391808303921461342e57612710908282111561341c577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146134ac578483111561341c57829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b50509061098f92506133b0565b90816060910312610310578051916040602083015192015161098f81612642565b81835290916001600160fb1b0383116103105760209260051b809284830137010190565b90602082528035602083015260208101358060130b809103610310576040830152604081013561352d81610514565b6001600160a01b031660608381019190915281013536829003601e19018112156103105701602081359101906001600160401b038111610310578060051b360382136103105760a08360808061098f96015201916134da565b6040516325f56f1160e01b81526001600160a01b039291606090829081906135b190600483016134fe565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104e9575f915f905f956136d6575b50841561368357816135fb612af9565b16917f000000000000000000000000000000000000000000000000000000000000000016821461367c57509060205f92600460405180958193634641257d60e01b83525af19081156104e957613657925f9261365b57506126db565b9190565b61367591925060203d6020116104e2576104d481836114f4565b905f612857565b9081613689575b50509190565b803b1561031057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104e9576136c3575b80613683565b80610d8f6136d0926114a6565b5f6136bd565b919450506136fc915060603d606011613704575b6136f481836114f4565b8101906134b9565b93905f6135eb565b503d6136ea565b6001600160ff1b03811161371c5790565b6024906040519063123baf0360e11b82526004820152fd5b613743611cc760985460801c90565b5f82126138155781613754916126be565b90613761610c4683613369565b6137766065549161ffff8360a01c16906133bf565b801561381057807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc35318686547936137b4611cc76098546001600160801b031690565b806137fa575050612c4d90925b6001600160a01b0316916137d58484613e02565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b612c4d9261380a92039084613439565b926137c1565b505050565b613331610c4691613828611522946126cb565b906126a3565b609954906001600160801b0382169182156139515760801c61388e61387f827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163147016126a3565b6138888561261c565b90614393565b90811561394a5761389e82613e4e565b93841561394257826138ca612d9161333161152296610c4696611ce3611d556133318d611b6f9a6126a3565b6138d481876143f9565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a161333161392661391588613369565b6098546001600160801b03166125d1565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b61395f6144e0565b1561396657565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f916139e4575b506139d257565b60405163e775715160e01b8152600490fd5b6139fd915060203d6020116116ed576116de81836114f4565b5f6139cb565b5f546001600160a01b0316330361185557565b908160a0910312610310578051916020820151916040810151916080606083015192015190565b90613a4661459c565b6040810151613a5361459c565b5f80546001600160a01b0319166001600160a01b03851617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190613aa19082612067565b0390a26020810151613ab161459c565b61271061ffff821611613b0757613aca613aef93613edd565b6065805461ffff60a01b191660a09290921b61ffff60a01b16919091179055516145ca565b613af76145fa565b613aff61459c565b61152261461b565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613b57575b50506118be57565b5f80516020614ded8339815191525416141590505f80613b4f565b90604051613b7f816114be565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613d2a575b613d1d5783613ce7575f5b609a5f526001600160a01b0316613bdc5f80516020614dcd8339815191528601613b72565b8051909790613bf3906001600160a01b03166117e8565b98613c18613c0c6020809b01516001600160601b031690565b6001600160601b031690565b948381108015613cdd575b613ccb5791600193979a95613c42613c4e939488035b838c0390614393565b80920198870391613439565b01970193808611801590613cc1575b613cb657609a5f528290613c7f5f80516020614dcd8339815191528701613b72565b805190890151969992966001600160a01b039091169460019392613c4e9290916001600160601b0390911690613c42908803613c39565b945050509250509190565b5081851015613c5d565b60405163e8722f8f60e01b8152600490fd5b50808b1115613c23565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b0316613bb7565b505093505050505f905f90565b508415613bac565b478211613df5575b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006002815414613de35760029055814710613dcb575f918291829182916001600160a01b03165af1613d8a612f68565b5015613db95761152260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b613dfd6148db565b613d3a565b613e0b82613369565b60985490613e236001600160801b0391828416612a83565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b609854906001600160801b03821681158015613e7d575b15613e705750905090565b61098f9260801c91613439565b508015613e65565b6098546001600160801b0381169082158015613ed5575b15613ea657505090565b60801c90613eb5828285613439565b9282156133ba5709613ec45790565b600181018091111561098f576125bd565b508115613e9c565b613ee5613978565b6001600160a01b03168015613f2d57606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b919290613f4a6148db565b60d154925f925f90613f5b81614952565b96613f64614cf4565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a10613fa6575050505050505050505090565b60b0613fb69101809989856149b4565b9960409a8c613ff28d51613fda602091828101906124b681611d148c8a8d87613244565b805191012091613feb858b8b6149d5565b3590613002565b52613ffd8184614984565b909361401d61401761400f8584614992565b9590936149a3565b906149e5565b908a3b15610310578b8f5f93614048915196879485946304512a2360e31b8652888c60048801614a01565b03816801bc16d674ec8000008d5af19384156104e95761409b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19582986140a7575b5097019e5192839283614a4f565b0390a101989097613f92565b80610d8f6140b4926114a6565b5f61408d565b906140c89495939291614a78565b1490565b9192915f915b8083106140e0575050501490565b9091926140fb6001916140f48685876149d5565b3590614d1d565b930191906140d2565b61410c6148db565b8160301161031057614017917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661414a614cf4565b906141616141588486614992565b969094866149a3565b94813b15610310576801bc16d674ec8000005f946141c797604051988996879586946304512a2360e31b8652608060048701526141b86141a58d6084890190612e5d565b60031994858983030160248a0152611efb565b92868403016044870152612e75565b90606483015203925af19081156104e9577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb192612c4d92614210575b5060405191829182614a3e565b614219906114a6565b5f614203565b9190614229613978565b6001600160a01b038316908115610d9b5780156142d55780614250611cc760985460801c90565b019361425a612c52565b85116142c357610c46946142819161427c61427485613e85565b978893613369565b613e02565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b909291926142f3613978565b6001600160a01b038216918215610d9b5781156142d5578161431a611cc760985460801c90565b01614323612c52565b81116142c357610c469561436a6142be927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9461427c61436288613e85565b9a8b93613369565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b9080821015612c7a575090565b609a5490600160401b8210156114b9576001820180609a55821015612f5657609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f80516020614dcd83398151915290910155565b90811580156144d8575b6144c657609a548061449057505f905b6001600160a01b03918216928301928310611a175781831161447057611522929161445b61444361446b93614c1f565b9161444c611515565b94166001600160a01b03168452565b6001600160601b03166020830152565b6143a0565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031690614413565b604051632ec8835b60e21b8152600490fd5b508015614403565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104e9575f91614536575090565b61098f915060203d6020116116ed576116de81836114f4565b60018060a01b03165f52609c60205260405f20908154818103908111611a17576145799255613369565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f80516020614e0d8339815191525460401c16156145b857565b604051631afcd79f60e31b8152600490fd5b6145d261459c565b80156145e857600181016145e35750565b609d55565b6040516331278a8760e01b8152600490fd5b61460261459c565b6801bc16d674ec800000614614612c52565b106145e857565b61462361459c565b61462b61459c565b61463361459c565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca00341061466c57612872343061421f565b60405163ea2559bb60e01b8152600490fd5b90816020910312610310575160ff811681036103105790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614721575b506146e757604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f80516020614ded833981519152840361470857611522929350614c52565b604051632a87526960e21b815260048101859052602490fd5b61473b91955060203d6020116104e2576104d481836114f4565b935f6146c1565b6001600160a01b0381165f9081526101376020526040902061476390612598565b906001600160801b0361477d83516001600160801b031690565b16156148d7576106f26147b491614792613978565b61479b846132b4565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104e957614817869361482592614851965f926148bf57506133bf565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104e9575f936148a0575b50501061488e57565b604051633684c65960e01b8152600490fd5b6148b7929350803d106104e2576104d481836114f4565b905f80614885565b610864919250863d88116104e2576104d481836114f4565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803180614910575050565b813b15610310575f9160448392604051948593849263f3fef3a360e01b845230600485015260248401525af180156104e9576149495750565b611522906114a6565b9061495c82612e95565b61496960405191826114f4565b828152809261497a601f1991612e95565b0190602036910137565b906030116103105790603090565b906090116103105760300190606090565b9060b0116103105760900190602090565b90939293848311610310578411610310578101920390565b9015612f565790565b9190811015612f565760051b0190565b3590602081106149f3575090565b5f199060200360031b1b1690565b9695949061325c93614a22614a30926060979560808c5260808c0191612e75565b9089820360208b0152611efb565b918783036040890152612e75565b90602061098f928181520190612e5d565b91602061098f938181520191612e75565b5f198114611a175760010190565b3561098f81612642565b9293919091805193614a8a84866126be565b614a93876126b0565b03614ad557614aa186614952565b945f8094885f965f5b828110614b0d575050159150614ae790505750505003614ad557614ad1915f190190613002565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614aff575050614ad190612ff5565b614b0992506149cc565b3590565b8a86861015614bc05750614b3f614b3a82614b31614b2a89614a60565b988c613002565b51955b876149d5565b614a6e565b15614ba5578a86861015614b845750614b7060019293614b68614b6188614a60565b978b613002565b515b90614d1d565b614b7a828d613002565b5201908a91614aaa565b92614b7090614b9f84614b9960019691614a60565b96613002565b51614b6a565b614b70600192936140f4614bb88c614a60565b9b8d8b6149d5565b91614b3a82614bd683614b99614b3f9591614a60565b5195614b34565b609a5480614bea57505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b03166117e8565b6001600160601b0390818111614c33571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b15614cd3575f80516020614ded83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2805115614cb85761287291614d3e565b505034614cc157565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b604051600160f81b60208201525f60218201523060601b602c8201526020815261098f816114be565b81811015614d31575f5260205260405f2090565b905f5260205260405f2090565b5f8061098f93602081519101845af4614d55612f68565b91614d7b565b614d636144e0565b614d6957565b6040516389a1dc6360e01b8152600490fd5b90614d905750805115613db957805190602001fd5b81511580614dc3575b614da1575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15614d9956fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122008c0a365c0eacebc60ec435e202f7516e2d88ee6141f2dc09523f89e64d7345864736f6c63430008160033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/shared/artifacts/EthPrivErc20Vault.json b/test/shared/artifacts/EthPrivErc20Vault.json new file mode 100644 index 00000000..c128d004 --- /dev/null +++ b/test/shared/artifacts/EthPrivErc20Vault.json @@ -0,0 +1,2020 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EthPrivErc20Vault", + "sourceName": "contracts/vaults/ethereum/EthPrivErc20Vault.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_validatorsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenVaultController", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "sharedMevEscrow", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitingAssetsClaimDelay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "CapacityExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimTooEarly", + "type": "error" + }, + { + "inputs": [], + "name": "Collateralized", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeePercent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHealthFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLtv", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPosition", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecurityDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShares", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTokenMeta", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidators", + "type": "error" + }, + { + "inputs": [], + "name": "LowLtv", + "type": "error" + }, + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + }, + { + "inputs": [], + "name": "NotCollateralized", + "type": "error" + }, + { + "inputs": [], + "name": "NotHarvested", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "PermitInvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RedemptionExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeFailed", + "type": "error" + }, + { + "inputs": [], + "name": "WhitelistAlreadyUpdated", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "WhitelistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + } + ], + "name": "WhitelisterUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keysManager_", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_whitelister", + "type": "address" + } + ], + "name": "setWhitelister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelister", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6101a034620001b057601f6200597a38819003918201601f19168301916001600160401b03831184841017620001b45780849260e094604052833981010312620001b0576200004e81620001c8565b6200005c60208301620001c8565b916200006b60408201620001c8565b926200007a60608301620001c8565b936200008960808401620001c8565b9160c06200009a60a08601620001c8565b9401519460805260a05260c0523060e052620000b5620001dd565b6101009346855261012093845260018060a01b03806101409216825261016092168252610180928352620000e8620001dd565b604051936156fd95866200027d8739608051868181611e9d015281816129f801528181613452015281816139fb01528181613c9b0152614a28015260a05186611aab015260c0518681816146620152614803015260e051868181611c99015261417b01525185612d740152518461301c01525183818161046501528181610a5501528181610e4101528181611462015281816136f70152613e1e015251828181610b3101528181610eed0152818161150e0152613d9d015251818181612d4f0152613a430152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203620001b057565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805460ff8160401c166200026a576001600160401b036002600160401b0319828216016200022b57505050565b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b60405163f92ee8a960e01b8152600490fdfe60806040526004361015610022575b3615610018575f80fd5b6100206136c2565b005b5f3560e01c806301e1d114146103d7578063066055e0146103d257806306fdde03146103cd57806307a2d13a146103c8578063095ea7b3146103c35780630d392cd9146103be57806318160ddd1461038257806318f72950146103b95780631a7ff553146103b4578063201b9eb5146103af57806322758a4a146103aa57806323b872dd146103a55780632999ad3f146103a05780632cdf74011461039b578063313ce567146103965780633229fa951461039157806333194c0a1461038c5780633644e515146103875780633a98ef3914610382578063439fab911461037d57806343e82a791461037857806346904840146103735780634ec96b221461036e5780634f1ef28614610369578063514e27081461036457806352d1902d1461035f57806353156f281461035a57806354fd4d50146103555780635c60da1b146103505780635cfc1a511461034b5780635dddf3a81461034657806360d60e6e1461034157806370a08231146102d357806372b410a81461033c57806376b58b90146103375780637bde82f2146103325780637ecebe001461032d5780637fd6f15c146103285780638697d2c2146103235780638ceab9aa1461031e57806395d89b41146103195780639b401cde14610314578063a1bf49aa1461030f578063a49a1e7d1461030a578063a9059cbb14610305578063aaa4e83614610300578063ac9650d8146102fb578063ad3cb1cc146102f6578063c6e6f592146102f1578063d505accf146102ec578063d83ad00c146102e7578063dd62ed3e146102e2578063e74b981b146102dd578063ef2a2158146102d8578063f04da65b146102d3578063f5e9de4d146102ce578063f6a6830f146102c9578063f851a440146102c4578063f9609f08146102bf5763f98f5b920361000e57612bb0565b612b9c565b612b74565b612b33565b6129a0565b611e37565b612918565b6128dd565b612899565b61284e565b61262d565b612604565b6125bf565b6124db565b6123da565b61239c565b612345565b612327565b612309565b612265565b6120f2565b6120cd565b6120a9565b61206e565b611f50565b611eff565b611e72565b611d97565b611d7d565b611d63565b611d2f565b611d14565b611cf0565b611c87565b611c19565b611993565b61189e565b611876565b611437565b61131e565b610927565b6112bb565b611281565b611255565b61123a565b611220565b610e17565b610d3b565b610d12565b6109e5565b6109b2565b61095b565b610858565b6107ac565b610775565b6106af565b61040a565b6103ea565b5f9103126103e657565b5f80fd5b346103e6575f3660031901126103e657602060cf5460801c604051908152f35b346103e65760203660031901126103e6576001600160801b03600435818116908181036103e657604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156105b0575f9361057f575b50335f90815261016e602052604090206104ae90612bf7565b936104c085516001600160801b031690565b161561056d57836105026104f56104e561051b946104e0610569996136e2565b613792565b83516001600160801b0316612c30565b6001600160801b03168252565b335f90815261016e60205260409020612c49565b612c49565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6105a291935060203d6020116105a9575b61059a8183610634565b810190612bdd565b915f610495565b503d610590565b612bec565b90600182811c921680156105e3575b60208310146105cf57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916105c4565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761061c57604052565b6105ed565b6001600160401b03811161061c57604052565b90601f801991011681019081106001600160401b0382111761061c57604052565b5f5b8381106106665750505f910152565b8181015183820152602001610657565b9060209161068f81518092818552858086019101610655565b601f01601f1916010190565b9060206106ac928181520190610676565b90565b346103e6575f3660031901126103e6576040515f80546106ce816105b5565b8084529060209060019081811690811561074b5750600114610707575b610569856106fb81870382610634565b6040519182918261069b565b5f80805293505f805160206156288339815191525b838510610738575050505081016020016106fb826105696106eb565b805486860184015293820193810161071c565b869550610569969350602092506106fb94915060ff191682840152151560051b82010192936106eb565b346103e65760203660031901126103e6576020610793600435612c72565b604051908152f35b6001600160a01b038116036103e657565b346103e65760403660031901126103e6576004356107c98161079b565b6001600160a01b0381169060243590821561083c576108048291335f52600260205260405f209060018060a01b03165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60405163d92e233d60e01b8152600490fd5b801515036103e657565b346103e6576040806003193601126103e6576004356108768161079b565b602435906108838261084e565b61026a546001600160a01b03919082163303610916571691825f5261026b918260205260ff825f20541692811515809415151461090557906108d991855f52602052825f209060ff801983541691151516179055565b519081527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3005b8251637d5bf36f60e11b8152600490fd5b8351634ca8886760e01b8152600490fd5b346103e6575f3660031901126103e65760206001600160801b0360cf5416604051908152f35b908160809103126103e65790565b60603660031901126103e6576004356109738161079b565b60243561097f8161079b565b604435906001600160401b0382116103e6576020926109ad6109a861079394369060040161094d565b612c98565b6135ab565b346103e65760203660031901126103e6576004356001600160401b0381116103e6576109a861002091369060040161094d565b346103e65760603660031901126103e6576004803590610a048261079b565b6024359060443592610a158461079b565b610a1d613c5f565b610a25613c80565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156105b0575f98610cf3575b50335f90815261016e602052604090208390610aae90612bf7565b946001600160801b03610ac887516001600160801b031690565b1615610c9157610ad7866136e2565b610b03610af6610ae689613792565b88516001600160801b0316612cec565b6001600160801b03168752565b335f90815260d3602052604090208490610b1e905b54612c72565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156105b057610bad928592610b71925f92610c72575b506137e8565b92610b8387516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156105b0575f93610c53575b505010610c455750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e5891610c0c610569976105163360018060a01b03165f5261016e60205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610c6a929350803d106105a95761059a8183610634565b905f80610bbf565b610c8a919250843d86116105a95761059a8183610634565b905f610b6b565b885163752a536d60e01b8152915083828681865afa80156105b057610cc2610cd19187945f91610cd6575b50613792565b6001600160801b031687860152565b610ad7565b610ced9150873d89116105a95761059a8183610634565b5f610cbc565b610d0b919850823d84116105a95761059a8183610634565b965f610a93565b346103e6575f3660031901126103e65761026a546040516001600160a01b039091168152602090f35b346103e65760603660031901126103e657600435610d588161079b565b60243590610d658261079b565b6001600160a01b0381165f8181526002602090815260408083203384529091529020546044359160018201610db5575b610da984610da4858883614a7c565b613d0b565b60405160018152602090f35b919093818503948511610de9575f928352600260209081526040808520338652909152909220939093559180610da9610d95565b612c1c565b60609060031901126103e65760043590602435610e0a8161079b565b906044356106ac8161079b565b346103e657610e2536610dee565b906001600160a01b038083161561083c57610e3e613c80565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103e65760408051631d8557d760e01b815260049491905f81878183875af180156105b057611207575b506001600160a01b0383165f90815261016e60205260409020610eb190612bf7565b6001600160801b03610eca82516001600160801b031690565b16156111f757610ed9816136e2565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156105b057610f48975f955f916111be575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156105b057610f63925f916111a157506137e8565b95610f81610b188960018060a01b03165f5260d360205260405f2090565b918288118015611191575b61118157908a610fc992610fa788516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156105b057670de0b6b3a764000093611005938d5f94611158575b5050610ff9610fff9161340e565b9261342b565b91613862565b101561114a578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156105b0577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c5350976111279561109f9361112c575b50506110826104f56104e58c613792565b6001600160a01b0386165f90815261016e60205260409020612c49565b6110a882614438565b906110e66110cb6110b885613792565b60cf5460801c036001600160801b031690565b6001600160801b0360cf549181199060801b1691161760cf55565b6110f0828661510e565b6110fa838961438a565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b8161114292903d106105a95761059a8183610634565b505f80611071565b835163185cfc6d60e11b8152fd5b610fff929450610ff9918161117892903d106105a95761059a8183610634565b9391508d610feb565b865163efda1a2760e01b81528490fd5b5061119a612d07565b8811610f8c565b6111b891508c8d3d106105a95761059a8183610634565b5f610b6b565b90506111e391955060a03d60a0116111f0575b6111db8183610634565b810190613ea4565b509692509050945f610f24565b503d6111d1565b815163673f032f60e11b81528690fd5b8061121461121a92610621565b806103dc565b5f610e8f565b346103e6575f3660031901126103e6576020610793612d07565b346103e6575f3660031901126103e657602060405160128152f35b346103e6575f3660031901126103e657602061126f612d36565b6040516001600160a01b039091168152f35b346103e6575f3660031901126103e65760206040517f3c60bf85548481aa53872c99e20f566d08c7fc12e0f05302f4002dedc8d45e4d8152f35b346103e6575f3660031901126103e6576020610793612d71565b9060206003198301126103e6576004356001600160401b03928382116103e657806023830112156103e65781600401359384116103e657602484830101116103e6576024019190565b611327366112d5565b905f805160206156a883398151915254916001600160401b0360ff8460401c161593168015908161142f575b6001149081611425575b15908161141c575b5061140a575f805160206156a8833981519152805467ffffffffffffffff1916600117905561139891836113e657612e84565b61139e57005b5f805160206156a8833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f805160206156a8833981519152805460ff60401b1916600160401b179055612e84565b60405163f92ee8a960e01b8152600490fd5b9050155f611365565b303b15915061135d565b849150611353565b346103e65761144536610dee565b906001600160a01b03908183161561083c5761145f613c80565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103e65760408051631d8557d760e01b815260049291905f81858183875af180156105b057611863575b506001600160a01b0384165f90815261016e602052604090206114d190612bf7565b926001600160801b036114eb85516001600160801b031690565b1615611855576114fa846136e2565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156105b0575f955f95611827575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156105b0575f99611808575b506001600160a01b038a165f90815260d36020526040902061159990610b18565b90818a1180156117f8575b6117e8576115df90866115be87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156105b0575f926117c7575b506115fd91926137e8565b116117b7578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156105b057859261179a575b506116468d613792565b84516001600160801b03169061165b91612c30565b6001600160801b031684526001600160a01b038a165f90815261016e602052604090208461168891612c49565b61169189614438565b9761169b8a613792565b60cf5460801c036001600160801b03166116ca906001600160801b0360cf549181199060801b1691161760cf55565b6116d4898c61510e565b6001600160a01b038b165f90815260d360205260409020546116f590612c72565b906116ff916137e8565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156105b0575f9361177b575b50501161176d575091611127917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd39594936110fa838961438a565b9051631d8fa13d60e31b8152fd5b611792929350803d106105a95761059a8183610634565b905f80611732565b6117b090833d85116105a95761059a8183610634565b505f61163c565b855163324b20e160e11b81528590fd5b6115fd92506117e290883d8a116105a95761059a8183610634565b916115f2565b875163efda1a2760e01b81528790fd5b50611801612d07565b8a116115a4565b611820919950853d87116105a95761059a8183610634565b975f611578565b61156592965061184791955060a03d60a0116111f0576111db8183610634565b505050959095949091611541565b905163673f032f60e11b8152fd5b8061121461187092610621565b5f6114af565b346103e6575f3660031901126103e657609c546040516001600160a01b039091168152602090f35b346103e65760203660031901126103e6576004356118bb8161079b565b60018060a01b03165f5261016e602052602060405f20604051906118de82610601565b54906001600160801b03918281169081835260801c84830152611906575b5116604051908152f35b61190f816136e2565b6118fc565b6040519060a082018281106001600160401b0382111761061c57604052565b6040519061194082610601565b565b6001600160401b03811161061c57601f01601f191660200190565b92919261196982611942565b916119776040519384610634565b8294818452818301116103e6578281602093845f960137010152565b6040806003193601126103e65760049081356119ae8161079b565b6024356001600160401b0381116103e657366023820112156103e6576119dd903690602481870135910161195d565b916119e6614171565b805192611a1d84611a0f60209363439fab9160e01b858401528460248401526044830190610676565b03601f198101865285610634565b611a25614171565b611a2d614424565b6001600160a01b03838116801592919087908415611be4575b8415611b76575b8415611b12575b50508215611a7c575b5050611a6d576100208383614d4b565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156105b0575f92611ae5575b5050155f80611a5d565b611b049250803d10611b0b575b611afc8183610634565b810190612f75565b5f80611adb565b503d611af2565b855163054fd4d560e41b81529294508391839182905afa9081156105b05760029160ff915f91611b49575b5016141591865f611a54565b611b699150843d8611611b6f575b611b618183610634565b810190614d36565b5f611b3d565b503d611b57565b935050835163198ca60560e11b815282818981875afa9081156105b05788917f3c60bf85548481aa53872c99e20f566d08c7fc12e0f05302f4002dedc8d45e4d915f91611bc7575b50141593611a4d565b611bde9150853d87116105a95761059a8183610634565b5f611bbe565b5f80516020615648833981519152549094508490611c12906001600160a01b03165b6001600160a01b031690565b1493611a46565b346103e65760203660031901126103e6576004356001600160a01b03611c3d612f54565b163303611c755780610107555f61010855337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346103e6575f3660031901126103e6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611cde5760206040515f805160206156488339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126103e6576001600160a01b03611d0b612d36565b163303611c7557005b346103e6575f3660031901126103e657602060405160018152f35b346103e6575f3660031901126103e6575f80516020615648833981519152546040516001600160a01b039091168152602090f35b346103e6575f3660031901126103e6576020610793612f46565b346103e6575f3660031901126103e657602061126f612f54565b346103e65760203660031901126103e65760d180549081905f6004355b848210611de557505050811015611dda57610569905b6040519081529081906020820190565b506105695f19611dca565b909193808316906001818518811c8301809311610de9575f8790525f805160206156888339815191528301546001600160a01b0316841015611e2c575050935b9190611db4565b909591019250611e25565b346103e65760203660031901126103e657600435611e548161079b565b60018060a01b03165f5260d3602052602060405f2054604051908152f35b346103e6575f3660031901126103e657604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156105b0576020915f91611ee2575b506040519015158152f35b611ef99150823d8411611b0b57611afc8183610634565b5f611ed7565b346103e65760803660031901126103e657610569611f33600435611f228161079b565b606435906044359060243590612f97565b604080519384526020840192909252908201529081906060820190565b346103e6576040806003193601126103e65760043560243591611f728361079b565b611f7a615541565b811561205e576001600160a01b038316801561204d57611f9983612c72565b92831561203c57611fa8612d07565b841161202b57611fdf8461056996611fd06110cb611fc584613792565b60cf5460801c612c30565b611fda843361510e565b61438a565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea8348090604090a361201d33613d0b565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346103e65760203660031901126103e65760043561208b8161079b565b60018060a01b03165f526003602052602060405f2054604051908152f35b346103e6575f3660031901126103e657602061ffff609c5460a01c16604051908152f35b346103e65760603660031901126103e657610569611f33604435602435600435613011565b346103e6576040806003193601126103e65760043590602435906121158261079b565b61211d613c5f565b821561205e576001600160a01b03821692831561204d57610569936121fe6121e28361216061215460d0546001600160801b031690565b6001600160801b031690565b816121c061217583612170615561565b613004565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a6121af81608081015b03601f198101835282610634565b5190205f5260d260205260405f2090565b55335f90815260d3602052604090206121da838254612f8a565b905501613792565b6001600160801b03166001600160801b031960d054161760d055565b82518481526020810183905233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f90604090a361223b33613d0b565b8151908152309033905f8051602061566883398151915290602090a3519081529081906020820190565b346103e6575f3660031901126103e6576040515f60018054612286816105b5565b808552916020916001811690811561074b57506001146122b057610569856106fb81870382610634565b60015f90815293507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8385106122f6575050505081016020016106fb826105696106eb565b80548686018401529382019381016122da565b346103e6575f3660031901126103e657602061010754604051908152f35b346103e6575f3660031901126103e657602061010854604051908152f35b346103e6576123977f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf612377366112d5565b9290612381614424565b60405191829160208352339560208401916131a5565b0390a2005b346103e65760403660031901126103e6576123c66004356123bc8161079b565b6024359033614a7c565b6123cf33613d0b565b602060405160018152f35b346103e65760203660031901126103e6576004356123f78161079b565b6123ff614424565b6001600160a01b0316801561083c5761010980546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156103e6578235916001600160401b0383116103e6576020808501948460051b0101116103e657565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b8483106124ad5750505050505090565b90919293949584806124cb600193603f198682030187528a51610676565b980193019301919493929061249d565b346103e65760203660031901126103e657600480356001600160401b0381116103e65761250c903690600401612448565b91612516836131dc565b925f5b81811061252e57604051806105698782612478565b5f8061253b83858861326b565b6040939161254d85518093819361328b565b0390305af49061255b613298565b91156125825750906001916125708288613332565b5261257b8187613332565b5001612519565b848260448151106103e6576125a681836125bb9301516024809183010191016132c7565b925162461bcd60e51b8152928392830161069b565b0390fd5b346103e6575f3660031901126103e6576105696040516125de81610601565b60058152640352e302e360dc1b6020820152604051918291602083526020830190610676565b346103e65760203660031901126103e6576020610793600435614438565b60ff8116036103e657565b346103e65760e03660031901126103e65760043561264a8161079b565b6024356126568161079b565b60443590606435926084359061266b82612622565b6001600160a01b0383811695909290861561083c5742811061283c576020915f9161275e61276a89878a6127216126a0612d71565b6001600160a01b0384165f9081526003602052604090209097908054906001820190556040519586948d8601968791959493909260a09360c08401977f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98552600180871b038092166020860152166040840152606083015260808201520152565b0391612735601f1993848101835282610634565b5190206040519384918983019687909160429261190160f01b8352600283015260228201520190565b03908101835282610634565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa156105b0575f5192828416801590811561282f575b5061281d5761280a85916127f57f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259660018060a01b03165f52600260205260405f2090565b9060018060a01b03165f5260205260405f2090565b5560405193845216918060208101611127565b6040516323389ba560e21b8152600490fd5b905083831614155f6127b0565b604051631ab7da6b60e01b8152600490fd5b346103e6575f3660031901126103e65760206001600160801b0360d05416604051908152f35b60409060031901126103e65760043561288c8161079b565b906024356106ac8161079b565b346103e65760206128d46128ac36612874565b6001600160a01b039182165f9081526002855260408082209290931681526020919091522090565b54604051908152f35b346103e65760203660031901126103e6576100206004356128fd8161079b565b612905614424565b6144c7565b908160a09103126103e65790565b346103e65760803660031901126103e6576001600160401b036004358181116103e65761294990369060040161290a565b6024358281116103e657612961903690600401612448565b6044929192358481116103e65761297c903690600401612448565b916064359586116103e657612998610020963690600401612448565b959094613442565b346103e6576040806003193601126103e6576004906001600160401b0382358181116103e6576129d3903690850161290a565b906024359081116103e6576129eb9036908501612448565b9390926129f6613c80565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156103e6575f8251809263837d444160e01b8252818381612a458a8a8301613377565b03925af180156105b057612b20575b506801bc16d674ec800000612a67612d07565b10612b13578083019360b0612a7c8686613239565b905003612b0557612ad0612ad49161010854976101075490612ac3612abb8b612aa58c8c613239565b6121a18b94929451938492602084019687613577565b519020613594565b60208151910120926147bd565b1590565b612af857610020600186612af1612aeb8888613239565b906147f5565b0161010855565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80611214612b2d92610621565b5f612a54565b346103e65760203660031901126103e657600435612b508161079b565b60018060a01b03165f5261026b602052602060ff60405f2054166040519015158152f35b346103e6575f3660031901126103e6576037546040516001600160a01b039091168152602090f35b6020610793612baa36612874565b906135ab565b346103e65760203660031901126103e657610020600435612bd08161079b565b612bd8614424565b614908565b908160209103126103e6575190565b6040513d5f823e3d90fd5b90604051612c0481610601565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211610de957565b815160209092015160801b6001600160801b0319166001600160801b0392909216919091179055565b60cf546001600160801b0381169081612c8a57505090565b916106ac9260801c90613862565b612ca1906139ca565b9080612cdd575b50612caf57565b612cb7615011565b80612cc0575b50565b5f906040519081525f8051602061566883398151915260203092a3565b612ce690613b60565b5f612ca8565b9190916001600160801b0380809416911601918211610de957565b4760d054612d1d6001600160801b038216612c72565b9060801c01908181115f14612d30570390565b50505f90565b6101a1546001600160a01b03168015612d4c5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b467f000000000000000000000000000000000000000000000000000000000000000003612d9e5760045490565b6106ac613ecb565b908160209103126103e657516106ac8161079b565b359061ffff821682036103e657565b9080601f830112156103e6578160206106ac9335910161195d565b906020828203126103e65781356001600160401b03928382116103e657019060a0828203126103e657612e16611914565b9282358452612e2760208401612dbb565b602085015260408301358181116103e65782612e44918501612dca565b604085015260608301358181116103e65782612e61918501612dca565b606085015260808301359081116103e657612e7c9201612dca565b608082015290565b60405163e7f6f22560e01b815290916020908183600481335afa9283156105b0575f93612f27575b50604051636f4fa30f60e01b8152938285600481335afa9081156105b05761194095612eef945f93612ef4575b5050612ee89192810190612de5565b9083613ff1565b6140e3565b612ee893509081612f1992903d10612f20575b612f118183610634565b810190612da6565b915f612ed9565b503d612f07565b612f3f919350823d8411612f2057612f118183610634565b915f612eac565b60d454806106ac57505f1990565b610109546001600160a01b0390811680612f7057506037541690565b905090565b908160209103126103e657516106ac8161084e565b91908203918211610de957565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612fe7929091612fd081608081016121a1565b5190205f5260d260205260405f20549283916141ef565b9091828103908111610de95792565b9060018201809211610de957565b91908201809211610de957565b929190915f936130417f000000000000000000000000000000000000000000000000000000000000000085613004565b421061317b5760408051336020820190815291810186905260608082018490528152601f199161308291613076608082610634565b51902094868433612f97565b909690958787811561316d5750505f90815260d2602052604081205560018211613126575b5050506130df6130c46130b985613792565b60d05460801c612c30565b6001600160801b0360d0549181199060801b1691161760d055565b6130e9833361438a565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b613164919297506131378785613004565b604080513360208201908152918101939093526060830182905290989091906121af90826080810161275e565b555f80806130a7565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b03811161061c5760051b60200190565b906131e6826131c5565b6131f36040519182610634565b8281528092613204601f19916131c5565b01905f5b82811061321457505050565b806060602080938501015201613208565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156103e657018035906001600160401b0382116103e6576020019181360383136103e657565b90821015613286576132829160051b810190613239565b9091565b613225565b908092918237015f815290565b3d156132c2573d906132a982611942565b916132b76040519384610634565b82523d5f602084013e565b606090565b6020818303126103e6578051906001600160401b0382116103e6570181601f820112156103e65780516132f981611942565b926133076040519485610634565b818452602082840101116103e6576106ac9160208085019101610655565b8051156132865760200190565b80518210156132865760209160051b010190565b9035601e19823603018112156103e65701602081359101916001600160401b0382116103e65781360383136103e657565b9060a06106ac926020815282356020820152602083013560408201526133b36133a36040850185613346565b84606085015260c08401916131a5565b906133e66133db6133c76060870187613346565b601f198587038101608087015295916131a5565b946080810190613346565b939092828603019101526131a5565b906801bc16d674ec8000009180830292830403610de957565b90670de0b6b3a764000091828102928184041490151715610de957565b9061271091828102928184041490151715610de957565b929094939195613450613c80565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156103e6576040965f8851809263837d444160e01b82528183816134a48c60048301613377565b03925af180156105b057613564575b506134bc612d07565b6134c5896133f5565b116135535787158015613539575b61352857916135049593916134fe89612ad097956134f861010754978c810190613239565b90614637565b946147ab565b613518575061194090610108540161010855565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061354687860186613239565b905060b0890214156134d3565b86516396d8043360e01b8152600490fd5b8061121461357192610621565b5f6134b3565b93929160209161358f916040875260408701916131a5565b930152565b906040519160208301526020825261194082610601565b919091335f5261026b60205260409260ff845f205416806136a7575b15610916576135d4613c80565b6001600160a01b03821691821561369657341561368557346135fb61215460cf5460801c90565b0190613605612f46565b8211613674579461364f7f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c926110cb969761364a6136423461446f565b988993613792565b614fa9565b51348152602081018590526001600160a01b039290921660408301523391606090a390565b85516304ffa0ff60e51b8152600490fd5b84516318374fd160e21b8152600490fd5b845163d92e233d60e01b8152600490fd5b506001600160a01b0382165f9081528490205460ff166135c7565b335f5261026b60205260ff60405f20541615611c7557612cbd343361494f565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91613773575b5060208201916001600160801b0391828451169182821461376c578361375f6104e0613767958584865116613862565b169052613792565b169052565b5050505050565b61378c915060203d6020116105a95761059a8183610634565b5f61372f565b6001600160801b03908181116137a6571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156137e3570490565b6137c5565b90808202905f1981840990828083109203918083039214613857576127109082821115613845577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146138d5578483111561384557829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b5050906106ac92506137d9565b908160609103126103e657805191604060208301519201516106ac8161084e565b81835290916001600160fb1b0383116103e65760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036103e657604083015260408101356139568161079b565b6001600160a01b031660608381019190915281013536829003601e19018112156103e65701602081359101906001600160401b0381116103e6578060051b360382136103e65760a0836080806106ac9601520191613903565b9190915f8382019384129112908015821691151617610de957565b6040516325f56f1160e01b81526001600160a01b039291606090829081906139f59060048301613927565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156105b0575f915f905f95613b1b575b508415613ac85781613a3f612d36565b16917f0000000000000000000000000000000000000000000000000000000000000000168214613ac157509060205f92600460405180958193634641257d60e01b83525af19081156105b057613a9c925f92613aa0575b506139af565b9190565b613aba91925060203d6020116105a95761059a8183610634565b905f613a96565b9081613ace575b50509190565b803b156103e657604051636ee3193160e11b815260048101929092525f908290602490829084905af180156105b057613b08575b80613ac8565b80611214613b1592610621565b5f613b02565b91945050613b41915060603d606011613b49575b613b398183610634565b8101906138e2565b93905f613a2f565b503d613b2f565b600160ff1b8114610de9575f0390565b613b6f61215460cf5460801c90565b5f8212613c465781613b8091613004565b90613b8d6110cb83613792565b613ba2609c549161ffff8360a01c16906137e8565b8015613c4157807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc3531868654793613be061215460cf546001600160801b031690565b80613c2b575050613c2690925b6001600160a01b031691613c018484614fa9565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613c2692613c3b92039084613862565b92613bed565b505050565b6104e06110cb91613c5961194094613b50565b90612f8a565b613c67614a0d565b15613c6e57565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91613cec575b50613cda57565b60405163e775715160e01b8152600490fd5b613d05915060203d602011611b0b57611afc8183610634565b5f613cd3565b6001600160a01b0381165f90815261016e60205260409020613d2c90612bf7565b906001600160801b03613d4683516001600160801b031690565b1615613ea057610b18613d7d91613d5b613c80565b613d64846136e2565b6001600160a01b03165f90815260d36020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156105b057613de08693613dee92613e1a965f92613e8857506137e8565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156105b0575f93613e69575b505010613e5757565b604051633684c65960e01b8152600490fd5b613e80929350803d106105a95761059a8183610634565b905f80613e4e565b610c8a919250863d88116105a95761059a8183610634565b5050565b908160a09103126103e6578051916020820151916040810151916080606083015192015190565b6040515f905f5490613edc826105b5565b9283825260209384830193600190866001821691825f14613fd1575050600114613f8e575b50509181613f17613f88936121a1950382610634565b519020604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f95810195865260208601929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69085015246606085015230608085015291829060a0850190565b51902090565b5f80805286935091905f805160206156288339815191525b828410613fbc5750505082010181613f17613f01565b80548685018601528794909301928101613fa6565b60ff1916875292151560051b85019092019250839150613f179050613f01565b919091613ffc614af8565b6080820151614009614af8565b603780546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190614058908261069b565b0390a2602082015192614069614af8565b61271061ffff8516116140d1576140c9936140866140b9936144c7565b609c549061ffff60a01b9060a01b169061ffff60a01b191617609c556140ac8351614b26565b6140b4614b56565b614b77565b6060604082015191015190614ba6565b611940614cd3565b604051638a81d3b360e01b8152600490fd5b6140eb614af8565b6140f481614908565b6001600160a01b03165f81815261026b602081905260409091205460ff16151560011461415f57815f5260205260405f20600160ff19825416179055604051600181527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3565b604051637d5bf36f60e11b8152600490fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163081149182156141af575b5050611cde57565b5f805160206156488339815191525416141590505f806141a7565b906040516141d781610601565b91546001600160a01b038116835260a01c6020830152565b60d1545f948594939091808410801590614382575b614375578361433f575f5b60d15f526001600160a01b03166142345f8051602061568883398151915286016141ca565b805190979061424b906001600160a01b0316611c06565b986142706142646020809b01516001600160601b031690565b6001600160601b031690565b948381108015614335575b6143235791600193979a9561429a6142a6939488035b838c0390614df6565b80920198870391613862565b01970193808611801590614319575b61430e5760d15f5282906142d75f8051602061568883398151915287016141ca565b805190890151969992966001600160a01b0390911694600193926142a69290916001600160601b039091169061429a908803614291565b945050509250509190565b50818510156142b5565b60405163e8722f8f60e01b8152600490fd5b50808b111561427b565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce28401546001600160a01b031661420f565b505093505050505f905f90565b508415614204565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0091600283541461441257600283558147106143fa575f918291829182916001600160a01b03165af16143dc613298565b50156143e85760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b6037546001600160a01b03163303611c7557565b60cf54906001600160801b03821681158015614467575b1561445a5750905090565b6106ac9260801c91613862565b50801561444f565b60cf546001600160801b03811690821580156144bf575b1561449057505090565b60801c9061449f828285613862565b9282156137e357096144ae5790565b60018101809111156106ac57612c1c565b508115614486565b6144cf613c80565b6001600160a01b0316801561451757609c80546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b90614533826131c5565b6145406040519182610634565b8281528092614551601f19916131c5565b0190602036910137565b906030116103e65790603090565b906090116103e65760300190606090565b9060b0116103e65760900190602090565b909392938483116103e65784116103e6578101920390565b90156132865790565b91908110156132865760051b0190565b3590602081106145ca575090565b5f199060200360031b1b1690565b9695949061358f936145f9614607926060979560808c5260808c01916131a5565b9089820360208b0152610676565b9187830360408901526131a5565b9060206106ac92818152019061318d565b9160206106ac9381815201916131a5565b9193929061010854925f925f9061464d81614529565b97614656614e03565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106146975750505050505050505050565b60b06146a791018099898561458b565b9960409a8d6146e38d516146cb60209182810190612abb816121a18c8a8d87613577565b8051910120916146dc858b8b6145ac565b3590613332565b526146ee818461455b565b909361470e6147086147008584614569565b95909361457a565b906145bc565b908a3b156103e6578b8f5f93614739915196879485946304512a2360e31b8652888c600488016145d8565b03816801bc16d674ec8000008d5af19384156105b05761478c60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298614798575b5097019e5192839283614626565b0390a101989097614684565b806112146147a592610621565b5f61477e565b906147b99495939291614e44565b1490565b9192915f915b8083106147d1575050501490565b9091926147ec6001916147e58685876145ac565b35906153c3565b930191906147c3565b816030116103e657614708917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316614833614e03565b9061484a6148418486614569565b9690948661457a565b94813b156103e6576801bc16d674ec8000005f946148b097604051988996879586946304512a2360e31b8652608060048701526148a161488e8d608489019061318d565b60031994858983030160248a0152610676565b928684030160448701526131a5565b90606483015203925af19081156105b0577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb192613c26926148f9575b5060405191829182614615565b61490290610621565b5f6148ec565b61026a80546001600160a01b0319166001600160a01b03929092169182179055337fda2bcad4d57ac529886ff995d07bce191c08b5424c8f5824de6c73f90cc623d45f80a3565b9190614959613c80565b6001600160a01b03831690811561083c5780156149fb578061498061215460cf5460801c90565b019361498a612f46565b85116149e9576110cb946149ac9161364a6149a48561446f565b978893613792565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c90606090a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91614a63575090565b6106ac915060203d602011611b0b57611afc8183610634565b6001600160a01b03908116919082158015614aee575b61083c57825f5260d360205260405f2090815492858403938411610de9575f805160206156688339815191529360209355614add8160018060a01b03165f5260d360205260405f2090565b8681540190556040519586521693a3565b5080821615614a92565b60ff5f805160206156a88339815191525460401c1615614b1457565b604051631afcd79f60e31b8152600490fd5b614b2e614af8565b8015614b445760018101614b3f5750565b60d455565b6040516331278a8760e01b8152600490fd5b614b5e614af8565b6801bc16d674ec800000614b70612f46565b10614b4457565b614b7f614af8565b6001600160a01b031680614b905750565b6101a180546001600160a01b0319169091179055565b614bae614af8565b601e8151118015614cc8575b614cb657614bc6614af8565b8051906001600160401b03821161061c57614bea82614be55f546105b5565b615179565b602090816001601f851114614c4257509180614c2092614c2795945f92614c37575b50508160011b915f199060031b1c19161790565b5f55615243565b611940614c32613ecb565b600455565b015190505f80614c0c565b5f80529190601f1984165f80516020615628833981519152935f905b828210614c9e575050916001939185614c2797969410614c86575b505050811b015f55615243565b01515f1960f88460031b161c191690555f8080614c79565b80600186978294978701518155019601940190614c5e565b604051632d3f993760e21b8152600490fd5b50600a825111614bba565b614cdb614af8565b614ce3614af8565b614ceb614af8565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca003410614d2457612cbd343061494f565b60405163ea2559bb60e01b8152600490fd5b908160209103126103e657516106ac81612622565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614dd5575b50614d9b57604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206156488339815191528403614dbc57611940929350615321565b604051632a87526960e21b815260048101859052602490fd5b614def91955060203d6020116105a95761059a8183610634565b935f614d75565b9080821015612f70575090565b604051600160f81b60208201525f60218201523060601b602c820152602081526106ac81610601565b5f198114610de95760010190565b356106ac8161084e565b9293919091805193614e568486613004565b614e5f87612ff6565b03614ea157614e6d86614529565b945f8094885f965f5b828110614ed9575050159150614eb390505750505003614ea157614e9d915f190190613332565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614ecb575050614e9d90613325565b614ed592506145a3565b3590565b8a86861015614f8c5750614f0b614f0682614efd614ef689614e2c565b988c613332565b51955b876145ac565b614e3a565b15614f71578a86861015614f505750614f3c60019293614f34614f2d88614e2c565b978b613332565b515b906153c3565b614f46828d613332565b5201908a91614e76565b92614f3c90614f6b84614f6560019691614e2c565b96613332565b51614f36565b614f3c600192936147e5614f848c614e2c565b9b8d8b6145ac565b91614f0682614fa283614f65614f0b9591614e2c565b5195614f00565b5f8051602061566883398151915260205f92614fc485613792565b60cf5490614fdc6001600160801b0391828416612cec565b6001600160801b031990921691161760cf556001600160a01b031680845260d3825260408085208054870190555194855293a3565b60d054906001600160801b0382169182156151085760801c6150456150368247612f8a565b61503f85612c72565b90614df6565b9081156151015761505582614438565b9384156150f957826150816130c46104e0611940966110cb966121706121e26104e08d611fc59a612f8a565b61508b818761543d565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16104e06150dd6150cc88613792565b60cf546001600160801b0316612c30565b6001600160801b03166001600160801b031960cf54161760cf55565b505f93505050565b505f925050565b505f9150565b6001600160a01b03165f81815260d360205260409020805483810391908211610de9575f935f80516020615668833981519152926020925561514f81613792565b60cf54906001600160801b03908183160316906001600160801b0319161760cf55604051908152a3565b601f8111615185575050565b5f80525f80516020615628833981519152906020601f840160051c830193106151c8575b601f0160051c01905b8181106151bd575050565b5f81556001016151b2565b90915081906151a9565b90601f82116151df575050565b60019160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906020601f840160051c83019310615239575b601f0160051c01905b81811061522f57505050565b5f81558201615223565b909150819061521a565b9081516001600160401b03811161061c5760019061526a8161526584546105b5565b6151d2565b602080601f831160011461529f5750819061529b9394955f92614c375750508160011b915f199060031b1c19161790565b9055565b90601f198316956152d160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690565b925f905b88821061530a57505083859697106152f2575b505050811b019055565b01515f1960f88460031b161c191690555f80806152e8565b8087859682949686015181550195019301906152d5565b90813b156153a2575f8051602061564883398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561538757612cbd91615524565b50503461539057565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b818110156153d7575f5260205260405f2090565b905f5260205260405f2090565b60d15490600160401b82101561061c57600182018060d1558210156132865760d15f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f8051602061568883398151915290910155565b908115801561551c575b61550a5760d154806154d457505f905b6001600160a01b03918216928301928310610de9578183116154b457611940929161549f6154876154af936155a3565b91615490611933565b94166001600160a01b03168452565b6001600160601b03166020830152565b6153e4565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b031690615457565b604051632ec8835b60e21b8152600490fd5b508015615447565b5f806106ac93602081519101845af461553b613298565b916155d6565b615549614a0d565b61554f57565b6040516389a1dc6360e01b8152600490fd5b60d1548061556e57505f90565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b0316611c06565b6001600160601b03908181116155b7571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b906155eb57508051156143e857805190602001fd5b8151158061561e575b6155fc575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156155f456fe290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce3f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212202e23b370e0941c06867beb0c0750c778738e9000991419280166e75e3fc3d99764736f6c63430008160033", + "deployedBytecode": "0x60806040526004361015610022575b3615610018575f80fd5b6100206136c2565b005b5f3560e01c806301e1d114146103d7578063066055e0146103d257806306fdde03146103cd57806307a2d13a146103c8578063095ea7b3146103c35780630d392cd9146103be57806318160ddd1461038257806318f72950146103b95780631a7ff553146103b4578063201b9eb5146103af57806322758a4a146103aa57806323b872dd146103a55780632999ad3f146103a05780632cdf74011461039b578063313ce567146103965780633229fa951461039157806333194c0a1461038c5780633644e515146103875780633a98ef3914610382578063439fab911461037d57806343e82a791461037857806346904840146103735780634ec96b221461036e5780634f1ef28614610369578063514e27081461036457806352d1902d1461035f57806353156f281461035a57806354fd4d50146103555780635c60da1b146103505780635cfc1a511461034b5780635dddf3a81461034657806360d60e6e1461034157806370a08231146102d357806372b410a81461033c57806376b58b90146103375780637bde82f2146103325780637ecebe001461032d5780637fd6f15c146103285780638697d2c2146103235780638ceab9aa1461031e57806395d89b41146103195780639b401cde14610314578063a1bf49aa1461030f578063a49a1e7d1461030a578063a9059cbb14610305578063aaa4e83614610300578063ac9650d8146102fb578063ad3cb1cc146102f6578063c6e6f592146102f1578063d505accf146102ec578063d83ad00c146102e7578063dd62ed3e146102e2578063e74b981b146102dd578063ef2a2158146102d8578063f04da65b146102d3578063f5e9de4d146102ce578063f6a6830f146102c9578063f851a440146102c4578063f9609f08146102bf5763f98f5b920361000e57612bb0565b612b9c565b612b74565b612b33565b6129a0565b611e37565b612918565b6128dd565b612899565b61284e565b61262d565b612604565b6125bf565b6124db565b6123da565b61239c565b612345565b612327565b612309565b612265565b6120f2565b6120cd565b6120a9565b61206e565b611f50565b611eff565b611e72565b611d97565b611d7d565b611d63565b611d2f565b611d14565b611cf0565b611c87565b611c19565b611993565b61189e565b611876565b611437565b61131e565b610927565b6112bb565b611281565b611255565b61123a565b611220565b610e17565b610d3b565b610d12565b6109e5565b6109b2565b61095b565b610858565b6107ac565b610775565b6106af565b61040a565b6103ea565b5f9103126103e657565b5f80fd5b346103e6575f3660031901126103e657602060cf5460801c604051908152f35b346103e65760203660031901126103e6576001600160801b03600435818116908181036103e657604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156105b0575f9361057f575b50335f90815261016e602052604090206104ae90612bf7565b936104c085516001600160801b031690565b161561056d57836105026104f56104e561051b946104e0610569996136e2565b613792565b83516001600160801b0316612c30565b6001600160801b03168252565b335f90815261016e60205260409020612c49565b612c49565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6105a291935060203d6020116105a9575b61059a8183610634565b810190612bdd565b915f610495565b503d610590565b612bec565b90600182811c921680156105e3575b60208310146105cf57565b634e487b7160e01b5f52602260045260245ffd5b91607f16916105c4565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761061c57604052565b6105ed565b6001600160401b03811161061c57604052565b90601f801991011681019081106001600160401b0382111761061c57604052565b5f5b8381106106665750505f910152565b8181015183820152602001610657565b9060209161068f81518092818552858086019101610655565b601f01601f1916010190565b9060206106ac928181520190610676565b90565b346103e6575f3660031901126103e6576040515f80546106ce816105b5565b8084529060209060019081811690811561074b5750600114610707575b610569856106fb81870382610634565b6040519182918261069b565b5f80805293505f805160206156288339815191525b838510610738575050505081016020016106fb826105696106eb565b805486860184015293820193810161071c565b869550610569969350602092506106fb94915060ff191682840152151560051b82010192936106eb565b346103e65760203660031901126103e6576020610793600435612c72565b604051908152f35b6001600160a01b038116036103e657565b346103e65760403660031901126103e6576004356107c98161079b565b6001600160a01b0381169060243590821561083c576108048291335f52600260205260405f209060018060a01b03165f5260205260405f2090565b556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b60405163d92e233d60e01b8152600490fd5b801515036103e657565b346103e6576040806003193601126103e6576004356108768161079b565b602435906108838261084e565b61026a546001600160a01b03919082163303610916571691825f5261026b918260205260ff825f20541692811515809415151461090557906108d991855f52602052825f209060ff801983541691151516179055565b519081527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3005b8251637d5bf36f60e11b8152600490fd5b8351634ca8886760e01b8152600490fd5b346103e6575f3660031901126103e65760206001600160801b0360cf5416604051908152f35b908160809103126103e65790565b60603660031901126103e6576004356109738161079b565b60243561097f8161079b565b604435906001600160401b0382116103e6576020926109ad6109a861079394369060040161094d565b612c98565b6135ab565b346103e65760203660031901126103e6576004356001600160401b0381116103e6576109a861002091369060040161094d565b346103e65760603660031901126103e6576004803590610a048261079b565b6024359060443592610a158461079b565b610a1d613c5f565b610a25613c80565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156105b0575f98610cf3575b50335f90815261016e602052604090208390610aae90612bf7565b946001600160801b03610ac887516001600160801b031690565b1615610c9157610ad7866136e2565b610b03610af6610ae689613792565b88516001600160801b0316612cec565b6001600160801b03168752565b335f90815260d3602052604090208490610b1e905b54612c72565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156105b057610bad928592610b71925f92610c72575b506137e8565b92610b8387516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156105b0575f93610c53575b505010610c455750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e5891610c0c610569976105163360018060a01b03165f5261016e60205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610c6a929350803d106105a95761059a8183610634565b905f80610bbf565b610c8a919250843d86116105a95761059a8183610634565b905f610b6b565b885163752a536d60e01b8152915083828681865afa80156105b057610cc2610cd19187945f91610cd6575b50613792565b6001600160801b031687860152565b610ad7565b610ced9150873d89116105a95761059a8183610634565b5f610cbc565b610d0b919850823d84116105a95761059a8183610634565b965f610a93565b346103e6575f3660031901126103e65761026a546040516001600160a01b039091168152602090f35b346103e65760603660031901126103e657600435610d588161079b565b60243590610d658261079b565b6001600160a01b0381165f8181526002602090815260408083203384529091529020546044359160018201610db5575b610da984610da4858883614a7c565b613d0b565b60405160018152602090f35b919093818503948511610de9575f928352600260209081526040808520338652909152909220939093559180610da9610d95565b612c1c565b60609060031901126103e65760043590602435610e0a8161079b565b906044356106ac8161079b565b346103e657610e2536610dee565b906001600160a01b038083161561083c57610e3e613c80565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103e65760408051631d8557d760e01b815260049491905f81878183875af180156105b057611207575b506001600160a01b0383165f90815261016e60205260409020610eb190612bf7565b6001600160801b03610eca82516001600160801b031690565b16156111f757610ed9816136e2565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156105b057610f48975f955f916111be575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156105b057610f63925f916111a157506137e8565b95610f81610b188960018060a01b03165f5260d360205260405f2090565b918288118015611191575b61118157908a610fc992610fa788516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156105b057670de0b6b3a764000093611005938d5f94611158575b5050610ff9610fff9161340e565b9261342b565b91613862565b101561114a578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156105b0577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c5350976111279561109f9361112c575b50506110826104f56104e58c613792565b6001600160a01b0386165f90815261016e60205260409020612c49565b6110a882614438565b906110e66110cb6110b885613792565b60cf5460801c036001600160801b031690565b6001600160801b0360cf549181199060801b1691161760cf55565b6110f0828661510e565b6110fa838961438a565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b8161114292903d106105a95761059a8183610634565b505f80611071565b835163185cfc6d60e11b8152fd5b610fff929450610ff9918161117892903d106105a95761059a8183610634565b9391508d610feb565b865163efda1a2760e01b81528490fd5b5061119a612d07565b8811610f8c565b6111b891508c8d3d106105a95761059a8183610634565b5f610b6b565b90506111e391955060a03d60a0116111f0575b6111db8183610634565b810190613ea4565b509692509050945f610f24565b503d6111d1565b815163673f032f60e11b81528690fd5b8061121461121a92610621565b806103dc565b5f610e8f565b346103e6575f3660031901126103e6576020610793612d07565b346103e6575f3660031901126103e657602060405160128152f35b346103e6575f3660031901126103e657602061126f612d36565b6040516001600160a01b039091168152f35b346103e6575f3660031901126103e65760206040517f3c60bf85548481aa53872c99e20f566d08c7fc12e0f05302f4002dedc8d45e4d8152f35b346103e6575f3660031901126103e6576020610793612d71565b9060206003198301126103e6576004356001600160401b03928382116103e657806023830112156103e65781600401359384116103e657602484830101116103e6576024019190565b611327366112d5565b905f805160206156a883398151915254916001600160401b0360ff8460401c161593168015908161142f575b6001149081611425575b15908161141c575b5061140a575f805160206156a8833981519152805467ffffffffffffffff1916600117905561139891836113e657612e84565b61139e57005b5f805160206156a8833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f805160206156a8833981519152805460ff60401b1916600160401b179055612e84565b60405163f92ee8a960e01b8152600490fd5b9050155f611365565b303b15915061135d565b849150611353565b346103e65761144536610dee565b906001600160a01b03908183161561083c5761145f613c80565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103e65760408051631d8557d760e01b815260049291905f81858183875af180156105b057611863575b506001600160a01b0384165f90815261016e602052604090206114d190612bf7565b926001600160801b036114eb85516001600160801b031690565b1615611855576114fa846136e2565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156105b0575f955f95611827575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156105b0575f99611808575b506001600160a01b038a165f90815260d36020526040902061159990610b18565b90818a1180156117f8575b6117e8576115df90866115be87516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156105b0575f926117c7575b506115fd91926137e8565b116117b7578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156105b057859261179a575b506116468d613792565b84516001600160801b03169061165b91612c30565b6001600160801b031684526001600160a01b038a165f90815261016e602052604090208461168891612c49565b61169189614438565b9761169b8a613792565b60cf5460801c036001600160801b03166116ca906001600160801b0360cf549181199060801b1691161760cf55565b6116d4898c61510e565b6001600160a01b038b165f90815260d360205260409020546116f590612c72565b906116ff916137e8565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156105b0575f9361177b575b50501161176d575091611127917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd39594936110fa838961438a565b9051631d8fa13d60e31b8152fd5b611792929350803d106105a95761059a8183610634565b905f80611732565b6117b090833d85116105a95761059a8183610634565b505f61163c565b855163324b20e160e11b81528590fd5b6115fd92506117e290883d8a116105a95761059a8183610634565b916115f2565b875163efda1a2760e01b81528790fd5b50611801612d07565b8a116115a4565b611820919950853d87116105a95761059a8183610634565b975f611578565b61156592965061184791955060a03d60a0116111f0576111db8183610634565b505050959095949091611541565b905163673f032f60e11b8152fd5b8061121461187092610621565b5f6114af565b346103e6575f3660031901126103e657609c546040516001600160a01b039091168152602090f35b346103e65760203660031901126103e6576004356118bb8161079b565b60018060a01b03165f5261016e602052602060405f20604051906118de82610601565b54906001600160801b03918281169081835260801c84830152611906575b5116604051908152f35b61190f816136e2565b6118fc565b6040519060a082018281106001600160401b0382111761061c57604052565b6040519061194082610601565b565b6001600160401b03811161061c57601f01601f191660200190565b92919261196982611942565b916119776040519384610634565b8294818452818301116103e6578281602093845f960137010152565b6040806003193601126103e65760049081356119ae8161079b565b6024356001600160401b0381116103e657366023820112156103e6576119dd903690602481870135910161195d565b916119e6614171565b805192611a1d84611a0f60209363439fab9160e01b858401528460248401526044830190610676565b03601f198101865285610634565b611a25614171565b611a2d614424565b6001600160a01b03838116801592919087908415611be4575b8415611b76575b8415611b12575b50508215611a7c575b5050611a6d576100208383614d4b565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156105b0575f92611ae5575b5050155f80611a5d565b611b049250803d10611b0b575b611afc8183610634565b810190612f75565b5f80611adb565b503d611af2565b855163054fd4d560e41b81529294508391839182905afa9081156105b05760029160ff915f91611b49575b5016141591865f611a54565b611b699150843d8611611b6f575b611b618183610634565b810190614d36565b5f611b3d565b503d611b57565b935050835163198ca60560e11b815282818981875afa9081156105b05788917f3c60bf85548481aa53872c99e20f566d08c7fc12e0f05302f4002dedc8d45e4d915f91611bc7575b50141593611a4d565b611bde9150853d87116105a95761059a8183610634565b5f611bbe565b5f80516020615648833981519152549094508490611c12906001600160a01b03165b6001600160a01b031690565b1493611a46565b346103e65760203660031901126103e6576004356001600160a01b03611c3d612f54565b163303611c755780610107555f61010855337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346103e6575f3660031901126103e6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003611cde5760206040515f805160206156488339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126103e6576001600160a01b03611d0b612d36565b163303611c7557005b346103e6575f3660031901126103e657602060405160018152f35b346103e6575f3660031901126103e6575f80516020615648833981519152546040516001600160a01b039091168152602090f35b346103e6575f3660031901126103e6576020610793612f46565b346103e6575f3660031901126103e657602061126f612f54565b346103e65760203660031901126103e65760d180549081905f6004355b848210611de557505050811015611dda57610569905b6040519081529081906020820190565b506105695f19611dca565b909193808316906001818518811c8301809311610de9575f8790525f805160206156888339815191528301546001600160a01b0316841015611e2c575050935b9190611db4565b909591019250611e25565b346103e65760203660031901126103e657600435611e548161079b565b60018060a01b03165f5260d3602052602060405f2054604051908152f35b346103e6575f3660031901126103e657604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156105b0576020915f91611ee2575b506040519015158152f35b611ef99150823d8411611b0b57611afc8183610634565b5f611ed7565b346103e65760803660031901126103e657610569611f33600435611f228161079b565b606435906044359060243590612f97565b604080519384526020840192909252908201529081906060820190565b346103e6576040806003193601126103e65760043560243591611f728361079b565b611f7a615541565b811561205e576001600160a01b038316801561204d57611f9983612c72565b92831561203c57611fa8612d07565b841161202b57611fdf8461056996611fd06110cb611fc584613792565b60cf5460801c612c30565b611fda843361510e565b61438a565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea8348090604090a361201d33613d0b565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346103e65760203660031901126103e65760043561208b8161079b565b60018060a01b03165f526003602052602060405f2054604051908152f35b346103e6575f3660031901126103e657602061ffff609c5460a01c16604051908152f35b346103e65760603660031901126103e657610569611f33604435602435600435613011565b346103e6576040806003193601126103e65760043590602435906121158261079b565b61211d613c5f565b821561205e576001600160a01b03821692831561204d57610569936121fe6121e28361216061215460d0546001600160801b031690565b6001600160801b031690565b816121c061217583612170615561565b613004565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a6121af81608081015b03601f198101835282610634565b5190205f5260d260205260405f2090565b55335f90815260d3602052604090206121da838254612f8a565b905501613792565b6001600160801b03166001600160801b031960d054161760d055565b82518481526020810183905233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f90604090a361223b33613d0b565b8151908152309033905f8051602061566883398151915290602090a3519081529081906020820190565b346103e6575f3660031901126103e6576040515f60018054612286816105b5565b808552916020916001811690811561074b57506001146122b057610569856106fb81870382610634565b60015f90815293507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8385106122f6575050505081016020016106fb826105696106eb565b80548686018401529382019381016122da565b346103e6575f3660031901126103e657602061010754604051908152f35b346103e6575f3660031901126103e657602061010854604051908152f35b346103e6576123977f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf612377366112d5565b9290612381614424565b60405191829160208352339560208401916131a5565b0390a2005b346103e65760403660031901126103e6576123c66004356123bc8161079b565b6024359033614a7c565b6123cf33613d0b565b602060405160018152f35b346103e65760203660031901126103e6576004356123f78161079b565b6123ff614424565b6001600160a01b0316801561083c5761010980546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156103e6578235916001600160401b0383116103e6576020808501948460051b0101116103e657565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b8483106124ad5750505050505090565b90919293949584806124cb600193603f198682030187528a51610676565b980193019301919493929061249d565b346103e65760203660031901126103e657600480356001600160401b0381116103e65761250c903690600401612448565b91612516836131dc565b925f5b81811061252e57604051806105698782612478565b5f8061253b83858861326b565b6040939161254d85518093819361328b565b0390305af49061255b613298565b91156125825750906001916125708288613332565b5261257b8187613332565b5001612519565b848260448151106103e6576125a681836125bb9301516024809183010191016132c7565b925162461bcd60e51b8152928392830161069b565b0390fd5b346103e6575f3660031901126103e6576105696040516125de81610601565b60058152640352e302e360dc1b6020820152604051918291602083526020830190610676565b346103e65760203660031901126103e6576020610793600435614438565b60ff8116036103e657565b346103e65760e03660031901126103e65760043561264a8161079b565b6024356126568161079b565b60443590606435926084359061266b82612622565b6001600160a01b0383811695909290861561083c5742811061283c576020915f9161275e61276a89878a6127216126a0612d71565b6001600160a01b0384165f9081526003602052604090209097908054906001820190556040519586948d8601968791959493909260a09360c08401977f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98552600180871b038092166020860152166040840152606083015260808201520152565b0391612735601f1993848101835282610634565b5190206040519384918983019687909160429261190160f01b8352600283015260228201520190565b03908101835282610634565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa156105b0575f5192828416801590811561282f575b5061281d5761280a85916127f57f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259660018060a01b03165f52600260205260405f2090565b9060018060a01b03165f5260205260405f2090565b5560405193845216918060208101611127565b6040516323389ba560e21b8152600490fd5b905083831614155f6127b0565b604051631ab7da6b60e01b8152600490fd5b346103e6575f3660031901126103e65760206001600160801b0360d05416604051908152f35b60409060031901126103e65760043561288c8161079b565b906024356106ac8161079b565b346103e65760206128d46128ac36612874565b6001600160a01b039182165f9081526002855260408082209290931681526020919091522090565b54604051908152f35b346103e65760203660031901126103e6576100206004356128fd8161079b565b612905614424565b6144c7565b908160a09103126103e65790565b346103e65760803660031901126103e6576001600160401b036004358181116103e65761294990369060040161290a565b6024358281116103e657612961903690600401612448565b6044929192358481116103e65761297c903690600401612448565b916064359586116103e657612998610020963690600401612448565b959094613442565b346103e6576040806003193601126103e6576004906001600160401b0382358181116103e6576129d3903690850161290a565b906024359081116103e6576129eb9036908501612448565b9390926129f6613c80565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156103e6575f8251809263837d444160e01b8252818381612a458a8a8301613377565b03925af180156105b057612b20575b506801bc16d674ec800000612a67612d07565b10612b13578083019360b0612a7c8686613239565b905003612b0557612ad0612ad49161010854976101075490612ac3612abb8b612aa58c8c613239565b6121a18b94929451938492602084019687613577565b519020613594565b60208151910120926147bd565b1590565b612af857610020600186612af1612aeb8888613239565b906147f5565b0161010855565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80611214612b2d92610621565b5f612a54565b346103e65760203660031901126103e657600435612b508161079b565b60018060a01b03165f5261026b602052602060ff60405f2054166040519015158152f35b346103e6575f3660031901126103e6576037546040516001600160a01b039091168152602090f35b6020610793612baa36612874565b906135ab565b346103e65760203660031901126103e657610020600435612bd08161079b565b612bd8614424565b614908565b908160209103126103e6575190565b6040513d5f823e3d90fd5b90604051612c0481610601565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211610de957565b815160209092015160801b6001600160801b0319166001600160801b0392909216919091179055565b60cf546001600160801b0381169081612c8a57505090565b916106ac9260801c90613862565b612ca1906139ca565b9080612cdd575b50612caf57565b612cb7615011565b80612cc0575b50565b5f906040519081525f8051602061566883398151915260203092a3565b612ce690613b60565b5f612ca8565b9190916001600160801b0380809416911601918211610de957565b4760d054612d1d6001600160801b038216612c72565b9060801c01908181115f14612d30570390565b50505f90565b6101a1546001600160a01b03168015612d4c5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b467f000000000000000000000000000000000000000000000000000000000000000003612d9e5760045490565b6106ac613ecb565b908160209103126103e657516106ac8161079b565b359061ffff821682036103e657565b9080601f830112156103e6578160206106ac9335910161195d565b906020828203126103e65781356001600160401b03928382116103e657019060a0828203126103e657612e16611914565b9282358452612e2760208401612dbb565b602085015260408301358181116103e65782612e44918501612dca565b604085015260608301358181116103e65782612e61918501612dca565b606085015260808301359081116103e657612e7c9201612dca565b608082015290565b60405163e7f6f22560e01b815290916020908183600481335afa9283156105b0575f93612f27575b50604051636f4fa30f60e01b8152938285600481335afa9081156105b05761194095612eef945f93612ef4575b5050612ee89192810190612de5565b9083613ff1565b6140e3565b612ee893509081612f1992903d10612f20575b612f118183610634565b810190612da6565b915f612ed9565b503d612f07565b612f3f919350823d8411612f2057612f118183610634565b915f612eac565b60d454806106ac57505f1990565b610109546001600160a01b0390811680612f7057506037541690565b905090565b908160209103126103e657516106ac8161084e565b91908203918211610de957565b604080516001600160a01b039092166020830190815290820193909352606081018290529092612fe7929091612fd081608081016121a1565b5190205f5260d260205260405f20549283916141ef565b9091828103908111610de95792565b9060018201809211610de957565b91908201809211610de957565b929190915f936130417f000000000000000000000000000000000000000000000000000000000000000085613004565b421061317b5760408051336020820190815291810186905260608082018490528152601f199161308291613076608082610634565b51902094868433612f97565b909690958787811561316d5750505f90815260d2602052604081205560018211613126575b5050506130df6130c46130b985613792565b60d05460801c612c30565b6001600160801b0360d0549181199060801b1691161760d055565b6130e9833361438a565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b613164919297506131378785613004565b604080513360208201908152918101939093526060830182905290989091906121af90826080810161275e565b555f80806130a7565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b03811161061c5760051b60200190565b906131e6826131c5565b6131f36040519182610634565b8281528092613204601f19916131c5565b01905f5b82811061321457505050565b806060602080938501015201613208565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156103e657018035906001600160401b0382116103e6576020019181360383136103e657565b90821015613286576132829160051b810190613239565b9091565b613225565b908092918237015f815290565b3d156132c2573d906132a982611942565b916132b76040519384610634565b82523d5f602084013e565b606090565b6020818303126103e6578051906001600160401b0382116103e6570181601f820112156103e65780516132f981611942565b926133076040519485610634565b818452602082840101116103e6576106ac9160208085019101610655565b8051156132865760200190565b80518210156132865760209160051b010190565b9035601e19823603018112156103e65701602081359101916001600160401b0382116103e65781360383136103e657565b9060a06106ac926020815282356020820152602083013560408201526133b36133a36040850185613346565b84606085015260c08401916131a5565b906133e66133db6133c76060870187613346565b601f198587038101608087015295916131a5565b946080810190613346565b939092828603019101526131a5565b906801bc16d674ec8000009180830292830403610de957565b90670de0b6b3a764000091828102928184041490151715610de957565b9061271091828102928184041490151715610de957565b929094939195613450613c80565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156103e6576040965f8851809263837d444160e01b82528183816134a48c60048301613377565b03925af180156105b057613564575b506134bc612d07565b6134c5896133f5565b116135535787158015613539575b61352857916135049593916134fe89612ad097956134f861010754978c810190613239565b90614637565b946147ab565b613518575061194090610108540161010855565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b5061354687860186613239565b905060b0890214156134d3565b86516396d8043360e01b8152600490fd5b8061121461357192610621565b5f6134b3565b93929160209161358f916040875260408701916131a5565b930152565b906040519160208301526020825261194082610601565b919091335f5261026b60205260409260ff845f205416806136a7575b15610916576135d4613c80565b6001600160a01b03821691821561369657341561368557346135fb61215460cf5460801c90565b0190613605612f46565b8211613674579461364f7f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c926110cb969761364a6136423461446f565b988993613792565b614fa9565b51348152602081018590526001600160a01b039290921660408301523391606090a390565b85516304ffa0ff60e51b8152600490fd5b84516318374fd160e21b8152600490fd5b845163d92e233d60e01b8152600490fd5b506001600160a01b0382165f9081528490205460ff166135c7565b335f5261026b60205260ff60405f20541615611c7557612cbd343361494f565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91613773575b5060208201916001600160801b0391828451169182821461376c578361375f6104e0613767958584865116613862565b169052613792565b169052565b5050505050565b61378c915060203d6020116105a95761059a8183610634565b5f61372f565b6001600160801b03908181116137a6571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b81156137e3570490565b6137c5565b90808202905f1981840990828083109203918083039214613857576127109082821115613845577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f19848209938380861095039480860395146138d5578483111561384557829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b5050906106ac92506137d9565b908160609103126103e657805191604060208301519201516106ac8161084e565b81835290916001600160fb1b0383116103e65760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036103e657604083015260408101356139568161079b565b6001600160a01b031660608381019190915281013536829003601e19018112156103e65701602081359101906001600160401b0381116103e6578060051b360382136103e65760a0836080806106ac9601520191613903565b9190915f8382019384129112908015821691151617610de957565b6040516325f56f1160e01b81526001600160a01b039291606090829081906139f59060048301613927565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156105b0575f915f905f95613b1b575b508415613ac85781613a3f612d36565b16917f0000000000000000000000000000000000000000000000000000000000000000168214613ac157509060205f92600460405180958193634641257d60e01b83525af19081156105b057613a9c925f92613aa0575b506139af565b9190565b613aba91925060203d6020116105a95761059a8183610634565b905f613a96565b9081613ace575b50509190565b803b156103e657604051636ee3193160e11b815260048101929092525f908290602490829084905af180156105b057613b08575b80613ac8565b80611214613b1592610621565b5f613b02565b91945050613b41915060603d606011613b49575b613b398183610634565b8101906138e2565b93905f613a2f565b503d613b2f565b600160ff1b8114610de9575f0390565b613b6f61215460cf5460801c90565b5f8212613c465781613b8091613004565b90613b8d6110cb83613792565b613ba2609c549161ffff8360a01c16906137e8565b8015613c4157807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc3531868654793613be061215460cf546001600160801b031690565b80613c2b575050613c2690925b6001600160a01b031691613c018484614fa9565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613c2692613c3b92039084613862565b92613bed565b505050565b6104e06110cb91613c5961194094613b50565b90612f8a565b613c67614a0d565b15613c6e57565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91613cec575b50613cda57565b60405163e775715160e01b8152600490fd5b613d05915060203d602011611b0b57611afc8183610634565b5f613cd3565b6001600160a01b0381165f90815261016e60205260409020613d2c90612bf7565b906001600160801b03613d4683516001600160801b031690565b1615613ea057610b18613d7d91613d5b613c80565b613d64846136e2565b6001600160a01b03165f90815260d36020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156105b057613de08693613dee92613e1a965f92613e8857506137e8565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156105b0575f93613e69575b505010613e5757565b604051633684c65960e01b8152600490fd5b613e80929350803d106105a95761059a8183610634565b905f80613e4e565b610c8a919250863d88116105a95761059a8183610634565b5050565b908160a09103126103e6578051916020820151916040810151916080606083015192015190565b6040515f905f5490613edc826105b5565b9283825260209384830193600190866001821691825f14613fd1575050600114613f8e575b50509181613f17613f88936121a1950382610634565b519020604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f95810195865260208601929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69085015246606085015230608085015291829060a0850190565b51902090565b5f80805286935091905f805160206156288339815191525b828410613fbc5750505082010181613f17613f01565b80548685018601528794909301928101613fa6565b60ff1916875292151560051b85019092019250839150613f179050613f01565b919091613ffc614af8565b6080820151614009614af8565b603780546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf91908190614058908261069b565b0390a2602082015192614069614af8565b61271061ffff8516116140d1576140c9936140866140b9936144c7565b609c549061ffff60a01b9060a01b169061ffff60a01b191617609c556140ac8351614b26565b6140b4614b56565b614b77565b6060604082015191015190614ba6565b611940614cd3565b604051638a81d3b360e01b8152600490fd5b6140eb614af8565b6140f481614908565b6001600160a01b03165f81815261026b602081905260409091205460ff16151560011461415f57815f5260205260405f20600160ff19825416179055604051600181527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3565b604051637d5bf36f60e11b8152600490fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163081149182156141af575b5050611cde57565b5f805160206156488339815191525416141590505f806141a7565b906040516141d781610601565b91546001600160a01b038116835260a01c6020830152565b60d1545f948594939091808410801590614382575b614375578361433f575f5b60d15f526001600160a01b03166142345f8051602061568883398151915286016141ca565b805190979061424b906001600160a01b0316611c06565b986142706142646020809b01516001600160601b031690565b6001600160601b031690565b948381108015614335575b6143235791600193979a9561429a6142a6939488035b838c0390614df6565b80920198870391613862565b01970193808611801590614319575b61430e5760d15f5282906142d75f8051602061568883398151915287016141ca565b805190890151969992966001600160a01b0390911694600193926142a69290916001600160601b039091169061429a908803614291565b945050509250509190565b50818510156142b5565b60405163e8722f8f60e01b8152600490fd5b50808b111561427b565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce28401546001600160a01b031661420f565b505093505050505f905f90565b508415614204565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0091600283541461441257600283558147106143fa575f918291829182916001600160a01b03165af16143dc613298565b50156143e85760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b6037546001600160a01b03163303611c7557565b60cf54906001600160801b03821681158015614467575b1561445a5750905090565b6106ac9260801c91613862565b50801561444f565b60cf546001600160801b03811690821580156144bf575b1561449057505090565b60801c9061449f828285613862565b9282156137e357096144ae5790565b60018101809111156106ac57612c1c565b508115614486565b6144cf613c80565b6001600160a01b0316801561451757609c80546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b90614533826131c5565b6145406040519182610634565b8281528092614551601f19916131c5565b0190602036910137565b906030116103e65790603090565b906090116103e65760300190606090565b9060b0116103e65760900190602090565b909392938483116103e65784116103e6578101920390565b90156132865790565b91908110156132865760051b0190565b3590602081106145ca575090565b5f199060200360031b1b1690565b9695949061358f936145f9614607926060979560808c5260808c01916131a5565b9089820360208b0152610676565b9187830360408901526131a5565b9060206106ac92818152019061318d565b9160206106ac9381815201916131a5565b9193929061010854925f925f9061464d81614529565b97614656614e03565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106146975750505050505050505050565b60b06146a791018099898561458b565b9960409a8d6146e38d516146cb60209182810190612abb816121a18c8a8d87613577565b8051910120916146dc858b8b6145ac565b3590613332565b526146ee818461455b565b909361470e6147086147008584614569565b95909361457a565b906145bc565b908a3b156103e6578b8f5f93614739915196879485946304512a2360e31b8652888c600488016145d8565b03816801bc16d674ec8000008d5af19384156105b05761478c60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298614798575b5097019e5192839283614626565b0390a101989097614684565b806112146147a592610621565b5f61477e565b906147b99495939291614e44565b1490565b9192915f915b8083106147d1575050501490565b9091926147ec6001916147e58685876145ac565b35906153c3565b930191906147c3565b816030116103e657614708917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316614833614e03565b9061484a6148418486614569565b9690948661457a565b94813b156103e6576801bc16d674ec8000005f946148b097604051988996879586946304512a2360e31b8652608060048701526148a161488e8d608489019061318d565b60031994858983030160248a0152610676565b928684030160448701526131a5565b90606483015203925af19081156105b0577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb192613c26926148f9575b5060405191829182614615565b61490290610621565b5f6148ec565b61026a80546001600160a01b0319166001600160a01b03929092169182179055337fda2bcad4d57ac529886ff995d07bce191c08b5424c8f5824de6c73f90cc623d45f80a3565b9190614959613c80565b6001600160a01b03831690811561083c5780156149fb578061498061215460cf5460801c90565b019361498a612f46565b85116149e9576110cb946149ac9161364a6149a48561446f565b978893613792565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c90606090a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156105b0575f91614a63575090565b6106ac915060203d602011611b0b57611afc8183610634565b6001600160a01b03908116919082158015614aee575b61083c57825f5260d360205260405f2090815492858403938411610de9575f805160206156688339815191529360209355614add8160018060a01b03165f5260d360205260405f2090565b8681540190556040519586521693a3565b5080821615614a92565b60ff5f805160206156a88339815191525460401c1615614b1457565b604051631afcd79f60e31b8152600490fd5b614b2e614af8565b8015614b445760018101614b3f5750565b60d455565b6040516331278a8760e01b8152600490fd5b614b5e614af8565b6801bc16d674ec800000614b70612f46565b10614b4457565b614b7f614af8565b6001600160a01b031680614b905750565b6101a180546001600160a01b0319169091179055565b614bae614af8565b601e8151118015614cc8575b614cb657614bc6614af8565b8051906001600160401b03821161061c57614bea82614be55f546105b5565b615179565b602090816001601f851114614c4257509180614c2092614c2795945f92614c37575b50508160011b915f199060031b1c19161790565b5f55615243565b611940614c32613ecb565b600455565b015190505f80614c0c565b5f80529190601f1984165f80516020615628833981519152935f905b828210614c9e575050916001939185614c2797969410614c86575b505050811b015f55615243565b01515f1960f88460031b161c191690555f8080614c79565b80600186978294978701518155019601940190614c5e565b604051632d3f993760e21b8152600490fd5b50600a825111614bba565b614cdb614af8565b614ce3614af8565b614ceb614af8565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca003410614d2457612cbd343061494f565b60405163ea2559bb60e01b8152600490fd5b908160209103126103e657516106ac81612622565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614dd5575b50614d9b57604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206156488339815191528403614dbc57611940929350615321565b604051632a87526960e21b815260048101859052602490fd5b614def91955060203d6020116105a95761059a8183610634565b935f614d75565b9080821015612f70575090565b604051600160f81b60208201525f60218201523060601b602c820152602081526106ac81610601565b5f198114610de95760010190565b356106ac8161084e565b9293919091805193614e568486613004565b614e5f87612ff6565b03614ea157614e6d86614529565b945f8094885f965f5b828110614ed9575050159150614eb390505750505003614ea157614e9d915f190190613332565b5190565b604051631a8a024960e11b8152600490fd5b919550929350159050614ecb575050614e9d90613325565b614ed592506145a3565b3590565b8a86861015614f8c5750614f0b614f0682614efd614ef689614e2c565b988c613332565b51955b876145ac565b614e3a565b15614f71578a86861015614f505750614f3c60019293614f34614f2d88614e2c565b978b613332565b515b906153c3565b614f46828d613332565b5201908a91614e76565b92614f3c90614f6b84614f6560019691614e2c565b96613332565b51614f36565b614f3c600192936147e5614f848c614e2c565b9b8d8b6145ac565b91614f0682614fa283614f65614f0b9591614e2c565b5195614f00565b5f8051602061566883398151915260205f92614fc485613792565b60cf5490614fdc6001600160801b0391828416612cec565b6001600160801b031990921691161760cf556001600160a01b031680845260d3825260408085208054870190555194855293a3565b60d054906001600160801b0382169182156151085760801c6150456150368247612f8a565b61503f85612c72565b90614df6565b9081156151015761505582614438565b9384156150f957826150816130c46104e0611940966110cb966121706121e26104e08d611fc59a612f8a565b61508b818761543d565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16104e06150dd6150cc88613792565b60cf546001600160801b0316612c30565b6001600160801b03166001600160801b031960cf54161760cf55565b505f93505050565b505f925050565b505f9150565b6001600160a01b03165f81815260d360205260409020805483810391908211610de9575f935f80516020615668833981519152926020925561514f81613792565b60cf54906001600160801b03908183160316906001600160801b0319161760cf55604051908152a3565b601f8111615185575050565b5f80525f80516020615628833981519152906020601f840160051c830193106151c8575b601f0160051c01905b8181106151bd575050565b5f81556001016151b2565b90915081906151a9565b90601f82116151df575050565b60019160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6906020601f840160051c83019310615239575b601f0160051c01905b81811061522f57505050565b5f81558201615223565b909150819061521a565b9081516001600160401b03811161061c5760019061526a8161526584546105b5565b6151d2565b602080601f831160011461529f5750819061529b9394955f92614c375750508160011b915f199060031b1c19161790565b9055565b90601f198316956152d160015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690565b925f905b88821061530a57505083859697106152f2575b505050811b019055565b01515f1960f88460031b161c191690555f80806152e8565b8087859682949686015181550195019301906152d5565b90813b156153a2575f8051602061564883398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561538757612cbd91615524565b50503461539057565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b818110156153d7575f5260205260405f2090565b905f5260205260405f2090565b60d15490600160401b82101561061c57600182018060d1558210156132865760d15f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f8051602061568883398151915290910155565b908115801561551c575b61550a5760d154806154d457505f905b6001600160a01b03918216928301928310610de9578183116154b457611940929161549f6154876154af936155a3565b91615490611933565b94166001600160a01b03168452565b6001600160601b03166020830152565b6153e4565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b031690615457565b604051632ec8835b60e21b8152600490fd5b508015615447565b5f806106ac93602081519101845af461553b613298565b916155d6565b615549614a0d565b61554f57565b6040516389a1dc6360e01b8152600490fd5b60d1548061556e57505f90565b60d15f527f695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce201546001600160a01b0316611c06565b6001600160601b03908181116155b7571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b906155eb57508051156143e857805190602001fd5b8151158061561e575b6155fc575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b156155f456fe290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef695fb3134ad82c3b8022bc5464edd0bcc9424ef672b52245dcb6ab2374327ce3f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212202e23b370e0941c06867beb0c0750c778738e9000991419280166e75e3fc3d99764736f6c63430008160033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/shared/artifacts/EthPrivVault.json b/test/shared/artifacts/EthPrivVault.json new file mode 100644 index 00000000..0283e6cb --- /dev/null +++ b/test/shared/artifacts/EthPrivVault.json @@ -0,0 +1,1708 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EthPrivVault", + "sourceName": "contracts/vaults/ethereum/EthPrivVault.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_validatorsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenVaultController", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "sharedMevEscrow", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitingAssetsClaimDelay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "CapacityExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimTooEarly", + "type": "error" + }, + { + "inputs": [], + "name": "Collateralized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeePercent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHealthFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLtv", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPosition", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecurityDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShares", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidators", + "type": "error" + }, + { + "inputs": [], + "name": "LowLtv", + "type": "error" + }, + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + }, + { + "inputs": [], + "name": "NotCollateralized", + "type": "error" + }, + { + "inputs": [], + "name": "NotHarvested", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "RedemptionExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeFailed", + "type": "error" + }, + { + "inputs": [], + "name": "WhitelistAlreadyUpdated", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "WhitelistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "whitelister", + "type": "address" + } + ], + "name": "WhitelisterUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keysManager_", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_whitelister", + "type": "address" + } + ], + "name": "setWhitelister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedAccounts", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelister", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x610180346200022657601f62004cba38819003918201601f19168301926001600160401b03929091838511838610176200022a578160e09284926040978852833981010312620002265762000054816200023e565b9262000063602083016200023e565b90620000718184016200023e565b9362000080606085016200023e565b946200008f608086016200023e565b9360c0620000a060a088016200023e565b9601519760805260a05260c0523060e05261010095865260018060a01b038061012096168652610140931683526101609384527ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff82851c1662000215578080831603620001d0575b5050505192614a669485620002548639608051858181611ade015281816122ee01528181612cc201528181613268015281816136050152614255015260a05185611724015260c051858181613cf60152613e97015260e0518581816119100152613811015251846128890152518381816103af0152818161071701528181610a530152818161107701528181612f6401526145de0152518281816107f301528181610aff01528181611123015261455d01525181818161263d01526132b00152f35b6001600160401b0319909116811790915581519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80806200010e565b835163f92ee8a960e01b8152600490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203620002265756fe60806040526004361015610022575b3615610018575f80fd5b610020612f2f565b005b5f3560e01c806301e1d11414610321578063066055e01461031c57806307a2d13a146103175780630d392cd91461031257806318f729501461030d5780631a7ff55314610308578063201b9eb51461030357806322758a4a146102fe5780632999ad3f146102f95780632cdf7401146102f45780633229fa95146102ef57806333194c0a146102ea5780633a98ef39146102e5578063439fab91146102e057806343e82a79146102db57806346904840146102d65780634ec96b22146102d15780634f1ef286146102cc578063514e2708146102c757806352d1902d146102c257806353156f28146102bd57806354fd4d50146102b85780635c60da1b146102b35780635cfc1a51146102ae5780635dddf3a8146102a957806360d60e6e146102a457806372b410a81461029f57806376b58b901461029a5780637bde82f2146102955780637fd6f15c146102905780638697d2c21461028b5780638ceab9aa146102865780639b401cde14610281578063a1bf49aa1461027c578063a49a1e7d14610277578063aaa4e83614610272578063ac9650d81461026d578063ad3cb1cc14610268578063c6e6f59214610263578063d83ad00c1461025e578063e74b981b14610259578063ef2a215814610254578063f04da65b1461024f578063f5e9de4d1461024a578063f6a6830f14610245578063f851a44014610240578063f9609f081461023b5763f98f5b920361000e576124b8565b61248e565b612467565b612426565b612296565b61225b565b6121d3565b612198565b612172565b612154565b61210f565b61201a565b611ed4565b611e7d565b611e60565b611e43565b611cfd565b611cd8565b611cb4565b611b91565b611b40565b611ab3565b611a0e565b6119f4565b6119da565b6119a6565b61198b565b611967565b6118fe565b611892565b61160c565b6114b3565b61148b565b61104c565b610f33565b610ec4565b610e8a565b610e5e565b610e44565b610a29565b6109d4565b6106a7565b610674565b61061d565b610540565b6104ff565b610354565b610334565b5f91031261033057565b5f80fd5b34610330575f36600319011261033057602060985460801c604051908152f35b34610330576020366003190112610330576001600160801b036004358181169081810361033057604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156104fa575f936104c9575b50335f908152610137602052604090206103f8906124ff565b9361040a85516001600160801b031690565b16156104b7578361044c61043f61042f6104659461042a6104b399612f4f565b612fff565b83516001600160801b0316612538565b6001600160801b03168252565b335f90815261013760205260409020612551565b612551565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104ec91935060203d6020116104f3575b6104e4818361158b565b8101906124e5565b915f6103df565b503d6104da565b6124f4565b3461033057602036600319011261033057602061051d600435612583565b604051908152f35b6001600160a01b0381160361033057565b8015150361033057565b34610330576040806003193601126103305760043561055e81610525565b6024359061056b82610536565b610201546001600160a01b039190821633036105fe571691825f52610202918260205260ff825f2054169281151580941515146105ed57906105c191855f52602052825f209060ff801983541691151516179055565b519081527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3005b8251637d5bf36f60e11b8152600490fd5b8351634ca8886760e01b8152600490fd5b908160809103126103305790565b60603660031901126103305760043561063581610525565b60243561064181610525565b604435906001600160401b0382116103305760209261066f61066a61051d94369060040161060f565b6125a9565b612e18565b34610330576020366003190112610330576004356001600160401b0381116103305761066a61002091369060040161060f565b346103305760603660031901126103305760048035906106c682610525565b60243590604435926106d784610525565b6106df6135c9565b6106e76135ea565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104fa575f986109b5575b50335f908152610137602052604090208390610770906124ff565b946001600160801b0361078a87516001600160801b031690565b16156109535761079986612f4f565b6107c56107b86107a889612fff565b88516001600160801b03166125da565b6001600160801b03168752565b335f908152609c6020526040902084906107e0905b54612583565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104fa5761086f928592610833925f92610934575b50613055565b9261084587516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104fa575f93610915575b5050106109075750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916108ce6104b3976104603360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b61092c929350803d106104f3576104e4818361158b565b905f80610881565b61094c919250843d86116104f3576104e4818361158b565b905f61082d565b885163752a536d60e01b8152915083828681865afa80156104fa576109846109939187945f91610998575b50612fff565b6001600160801b031687860152565b610799565b6109af9150873d89116104f3576104e4818361158b565b5f61097e565b6109cd919850823d84116104f3576104e4818361158b565b965f610755565b34610330575f36600319011261033057610201546040516001600160a01b039091168152602090f35b60609060031901126103305760043590602435610a1981610525565b90604435610a2681610525565b90565b3461033057610a37366109fd565b906001600160a01b0380831615610e3257610a506135ea565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103305760408051631d8557d760e01b815260049491905f81878183875af180156104fa57610e19575b506001600160a01b0383165f90815261013760205260409020610ac3906124ff565b6001600160801b03610adc82516001600160801b031690565b1615610e0957610aeb81612f4f565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104fa57610b5a975f955f91610dd0575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104fa57610b75925f91610db35750613055565b95610b936107da8960018060a01b03165f52609c60205260405f2090565b918288118015610da3575b610d9357908a610bdb92610bb988516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104fa57670de0b6b3a764000093610c17938d5f94610d6a575b5050610c0b610c1191612c7e565b92612c9b565b916130cf565b1015610d5c578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104fa577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610d3995610cb193610d3e575b5050610c9461043f61042f8c612fff565b6001600160a01b0386165f90815261013760205260409020612551565b610cba82613acd565b90610cf8610cdd610cca85612fff565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610d0282866142a9565b610d0c8389613a20565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610d5492903d106104f3576104e4818361158b565b505f80610c83565b835163185cfc6d60e11b8152fd5b610c11929450610c0b9181610d8a92903d106104f3576104e4818361158b565b9391508d610bfd565b865163efda1a2760e01b81528490fd5b50610dac6125f5565b8811610b9e565b610dca91508c8d3d106104f3576104e4818361158b565b5f61082d565b9050610df591955060a03d60a011610e02575b610ded818361158b565b810190613675565b509692509050945f610b36565b503d610de3565b815163673f032f60e11b81528690fd5b80610e26610e2c9261155d565b80610326565b5f610aa1565b60405163d92e233d60e01b8152600490fd5b34610330575f36600319011261033057602061051d6125f5565b34610330575f366003190112610330576020610e78612624565b6040516001600160a01b039091168152f35b34610330575f3660031901126103305760206040517fa90b5863127e5f962890f832f07b9f40c8df2fc043326a0e4b538552d600f2d98152f35b34610330575f3660031901126103305760206001600160801b0360985416604051908152f35b906020600319830112610330576004356001600160401b039283821161033057806023830112156103305781600401359384116103305760248483010111610330576024019190565b610f3c36610eea565b905f80516020614a1183398151915254916001600160401b0360ff8460401c1615931680159081611044575b600114908161103a575b159081611031575b5061101f575f80516020614a11833981519152805467ffffffffffffffff19166001179055610fad9183610ffb576126f3565b610fb357005b5f80516020614a11833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020614a11833981519152805460ff60401b1916600160401b1790556126f3565b60405163f92ee8a960e01b8152600490fd5b9050155f610f7a565b303b159150610f72565b849150610f68565b346103305761105a366109fd565b906001600160a01b039081831615610e32576110746135ea565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103305760408051631d8557d760e01b815260049291905f81858183875af180156104fa57611478575b506001600160a01b0384165f908152610137602052604090206110e6906124ff565b926001600160801b0361110085516001600160801b031690565b161561146a5761110f84612f4f565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104fa575f955f9561143c575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104fa575f9961141d575b506001600160a01b038a165f908152609c602052604090206111ae906107da565b90818a11801561140d575b6113fd576111f490866111d387516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104fa575f926113dc575b506112129192613055565b116113cc578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104fa5785926113af575b5061125b8d612fff565b84516001600160801b03169061127091612538565b6001600160801b031684526001600160a01b038a165f908152610137602052604090208461129d91612551565b6112a689613acd565b976112b08a612fff565b60985460801c036001600160801b03166112df906001600160801b036098549181199060801b16911617609855565b6112e9898c6142a9565b6001600160a01b038b165f908152609c602052604090205461130a90612583565b9061131491613055565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104fa575f93611390575b505011611382575091610d39917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610d0c8389613a20565b9051631d8fa13d60e31b8152fd5b6113a7929350803d106104f3576104e4818361158b565b905f80611347565b6113c590833d85116104f3576104e4818361158b565b505f611251565b855163324b20e160e11b81528590fd5b61121292506113f790883d8a116104f3576104e4818361158b565b91611207565b875163efda1a2760e01b81528790fd5b506114166125f5565b8a116111b9565b611435919950853d87116104f3576104e4818361158b565b975f61118d565b61117a92965061145c91955060a03d60a011610e0257610ded818361158b565b505050959095949091611156565b905163673f032f60e11b8152fd5b80610e266114859261155d565b5f6110c4565b34610330575f366003190112610330576065546040516001600160a01b039091168152602090f35b34610330576020366003190112610330576004356114d081610525565b60018060a01b03165f52610137602052602060405f20604051906114f38261153d565b54906001600160801b03918281169081835260801c8483015261151b575b5116604051908152f35b61152481612f4f565b611511565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761155857604052565b611529565b6001600160401b03811161155857604052565b606081019081106001600160401b0382111761155857604052565b90601f801991011681019081106001600160401b0382111761155857604052565b604051906115b98261153d565b565b6001600160401b03811161155857601f01601f191660200190565b9291926115e2826115bb565b916115f0604051938461158b565b829481845281830111610330578281602093845f960137010152565b60408060031936011261033057600490813561162781610525565b6024356001600160401b03811161033057366023820112156103305761165690369060248187013591016115d6565b9161165f613807565b8051926116968461168860209363439fab9160e01b858401528460248401526044830190611f92565b03601f19810186528561158b565b61169e613807565b6116a6613aba565b6001600160a01b0383811680159291908790841561185d575b84156117ef575b841561178b575b505082156116f5575b50506116e6576100208383614420565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104fa575f9261175e575b5050155f806116d6565b61177d9250803d10611784575b611775818361158b565b8101906127e2565b5f80611754565b503d61176b565b855163054fd4d560e41b81529294508391839182905afa9081156104fa5760029160ff915f916117c2575b5016141591865f6116cd565b6117e29150843d86116117e8575b6117da818361158b565b810190614407565b5f6117b6565b503d6117d0565b935050835163198ca60560e11b815282818981875afa9081156104fa5788917fa90b5863127e5f962890f832f07b9f40c8df2fc043326a0e4b538552d600f2d9915f91611840575b501415936116c6565b6118579150853d87116104f3576104e4818361158b565b5f611837565b5f805160206149f183398151915254909450849061188b906001600160a01b03165b6001600160a01b031690565b14936116bf565b34610330576020366003190112610330576004356001600160a01b036118b66127c3565b1633036118ec578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b34610330575f366003190112610330577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036119555760206040515f805160206149f18339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f366003190112610330576001600160a01b03611982612624565b1633036118ec57005b34610330575f36600319011261033057602060405160018152f35b34610330575f366003190112610330575f805160206149f1833981519152546040516001600160a01b039091168152602090f35b34610330575f36600319011261033057602061051d6127b5565b34610330575f366003190112610330576020610e786127c3565b3461033057602036600319011261033057609a80549081905f6004355b848210611a5c57505050811015611a51576104b3905b6040519081529081906020820190565b506104b35f19611a41565b909193808316906001818518811c8301809311611aae575f8790525f805160206149d18339815191528301546001600160a01b0316841015611aa3575050935b9190611a2b565b909591019250611a9c565b612524565b34610330575f36600319011261033057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104fa576020915f91611b23575b506040519015158152f35b611b3a9150823d841161178457611775818361158b565b5f611b18565b34610330576080366003190112610330576104b3611b74600435611b6381610525565b606435906044359060243590612804565b604080519384526020840192909252908201529081906060820190565b34610330576040806003193601126103305760043560243591611bb383610525565b611bbb61495f565b8115611ca4576001600160a01b0383168015611c9357611bda83612583565b928315611c8257611be96125f5565b8411611c7157611c20846104b396611c11610cdd611c0684612fff565b60985460801c612538565b611c1b84336142a9565b613a20565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611c63336144cb565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b34610330575f36600319011261033057602061ffff60655460a01c16604051908152f35b34610330576060366003190112610330576104b3611b7460443560243560043561287e565b3461033057604080600319360112610330576004359060243590611d2082610525565b611d286135c9565b8215611ca4576001600160a01b0382168015611c935783611e08611dec6104b396611d6a611d5e6099546001600160801b031690565b6001600160801b031690565b81611dca611d7f83611d7a61480a565b612871565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611db981608081015b03601f19810183528261158b565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611de48382546127f7565b905501612fff565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611c57565b34610330575f36600319011261033057602060d054604051908152f35b34610330575f36600319011261033057602060d154604051908152f35b3461033057611ecf7f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611eaf36610eea565b9290611eb9613aba565b6040519182916020835233956020840191612a15565b0390a2005b3461033057602036600319011261033057600435611ef181610525565b611ef9613aba565b6001600160a01b03168015610e325760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f84011215610330578235916001600160401b038311610330576020808501948460051b01011161033057565b5f5b838110611f825750505f910152565b8181015183820152602001611f73565b90602091611fab81518092818552858086019101611f71565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611fec5750505050505090565b909192939495848061200a600193603f198682030187528a51611f92565b9801930193019194939290611fdc565b3461033057602036600319011261033057600480356001600160401b0381116103305761204b903690600401611f41565b9161205583612a4c565b925f5b81811061206d57604051806104b38782611fb7565b5f8061207a838588612adb565b6040939161208c855180938193612afb565b0390305af49061209a612b08565b91156120c15750906001916120af8288612ba2565b526120ba8187612ba2565b5001612058565b84826044815110610330576120e581836120fa930151602480918301019101612b37565b925162461bcd60e51b815292839283016120fe565b0390fd5b906020610a26928181520190611f92565b34610330575f366003190112610330576104b360405161212e8161153d565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611f92565b3461033057602036600319011261033057602061051d600435613acd565b34610330575f3660031901126103305760206001600160801b0360995416604051908152f35b34610330576020366003190112610330576100206004356121b881610525565b6121c0613aba565b613b5c565b908160a09103126103305790565b34610330576080366003190112610330576001600160401b03600435818111610330576122049036906004016121c5565b6024358281116103305761221c903690600401611f41565b60449291923584811161033057612237903690600401611f41565b9160643595861161033057612253610020963690600401611f41565b959094612cb2565b346103305760203660031901126103305760043561227881610525565b60018060a01b03165f52609c602052602060405f2054604051908152f35b3461033057604080600319360112610330576004906001600160401b038235818111610330576122c990369085016121c5565b90602435908111610330576122e19036908501611f41565b9390926122ec6135ea565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610330575f8251809263837d444160e01b825281838161233b8a8a8301612be7565b03925af180156104fa57612413575b506801bc16d674ec80000061235d6125f5565b10612406578083019360b06123728686612aa9565b9050036123f8576123c46123c89160d1549760d054906123b76123af8b6123998c8c612aa9565b611dab8b94929451938492602084019687612de4565b519020612e01565b6020815191012092613e51565b1590565b6123eb576100206001866123e56123df8888612aa9565b90613e89565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610e266124209261155d565b5f61234a565b346103305760203660031901126103305760043561244381610525565b60018060a01b03165f52610202602052602060ff60405f2054166040519015158152f35b34610330575f366003190112610330575f546040516001600160a01b039091168152602090f35b604036600319011261033057602061051d6004356124ab81610525565b6024359061066f82610525565b34610330576020366003190112610330576100206004356124d881610525565b6124e0613aba565b613f9c565b90816020910312610330575190565b6040513d5f823e3d90fd5b9060405161250c8161153d565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211611aae57565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b038116908161259b57505090565b91610a269260801c906130cf565b6125b290613237565b90806125cb575b506125c057565b6125c86134cc565b50565b6125d4906133cd565b5f6125b9565b9190916001600160801b0380809416911601918211611aae57565b4760995461260b6001600160801b038216612583565b9060801c01908181115f1461261e570390565b50505f90565b61016a546001600160a01b0316801561263a5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b908160209103126103305751610a2681610525565b906020828203126103305781356001600160401b039283821161033057019160608383031261033057604051926126aa84611570565b80358452602081013561ffff81168103610330576020850152604081013591821161033057019080601f83011215610330578160206126eb933591016115d6565b604082015290565b60405163e7f6f22560e01b815290916020908183600481335afa9283156104fa575f93612796575b50604051636f4fa30f60e01b8152938285600481335afa9081156104fa576115b99561275e945f93612763575b50506127579192810190612674565b908361369c565b613779565b6127579350908161278892903d1061278f575b612780818361158b565b81019061265f565b915f612748565b503d612776565b6127ae919350823d841161278f57612780818361158b565b915f61271b565b609d5480610a2657505f1990565b60d2546001600160a01b03908116806127dd57505f541690565b905090565b908160209103126103305751610a2681610536565b91908203918211611aae57565b604080516001600160a01b03909216602083019081529082019390935260608101829052909261285492909161283d8160808101611dab565b5190205f52609b60205260405f2054928391613885565b9091828103908111611aae5792565b9060018201809211611aae57565b91908201809211611aae57565b929190915f936128ae7f000000000000000000000000000000000000000000000000000000000000000085612871565b42106129eb5760408051336020820190815291810186905260608082018490528152601f19916128ef916128e360808261158b565b51902094868433612804565b90969095878781156129dd5750505f908152609b602052604081205560018211612993575b50505061294c61293161292685612fff565b60995460801c612538565b6001600160801b036099549181199060801b16911617609955565b6129568333613a20565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b6129d4919297506129a48785612871565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611db9908261158b565b555f8080612914565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116115585760051b60200190565b90612a5682612a35565b612a63604051918261158b565b8281528092612a74601f1991612a35565b01905f5b828110612a8457505050565b806060602080938501015201612a78565b634e487b7160e01b5f52603260045260245ffd5b903590601e198136030182121561033057018035906001600160401b0382116103305760200191813603831361033057565b90821015612af657612af29160051b810190612aa9565b9091565b612a95565b908092918237015f815290565b3d15612b32573d90612b19826115bb565b91612b27604051938461158b565b82523d5f602084013e565b606090565b602081830312610330578051906001600160401b038211610330570181601f82011215610330578051612b69816115bb565b92612b77604051948561158b565b8184526020828401011161033057610a269160208085019101611f71565b805115612af65760200190565b8051821015612af65760209160051b010190565b9035601e19823603018112156103305701602081359101916001600160401b03821161033057813603831361033057565b9060a0610a2692602081528235602082015260208301356040820152612c23612c136040850185612bb6565b84606085015260c0840191612a15565b90612c56612c4b612c376060870187612bb6565b601f19858703810160808701529591612a15565b946080810190612bb6565b93909282860301910152612a15565b906801bc16d674ec8000009180830292830403611aae57565b90670de0b6b3a764000091828102928184041490151715611aae57565b9061271091828102928184041490151715611aae57565b929094939195612cc06135ea565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b15610330576040965f8851809263837d444160e01b8252818381612d148c60048301612be7565b03925af180156104fa57612dd1575b50612d2c6125f5565b612d3589612c65565b11612dc05787158015612da6575b612d955791612d73959391612d6d896123c49795612d6760d054978c810190612aa9565b90613ccc565b94613e3f565b612d8557506115b99060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b50612db387860186612aa9565b905060b089021415612d43565b86516396d8043360e01b8152600490fd5b80610e26612dde9261155d565b5f612d23565b939291602091612dfc91604087526040870191612a15565b930152565b90604051916020830152602082526115b98261153d565b919091335f5261020260205260409260ff845f20541680612f14575b156105fe57612e416135ea565b6001600160a01b038216918215612f03573415612ef25734612e68611d5e60985460801c90565b0190612e726127b5565b8211612ee15794612ebc7f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c92610cdd9697612eb7612eaf34613b04565b988993612fff565b6140a1565b51348152602081018590526001600160a01b039290921660408301523391606090a390565b85516304ffa0ff60e51b8152600490fd5b84516318374fd160e21b8152600490fd5b845163d92e233d60e01b8152600490fd5b506001600160a01b0382165f9081528490205460ff16612e34565b335f5261020260205260ff60405f205416156118ec576125c83433613fe3565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91612fe0575b5060208201916001600160801b03918284511691828214612fd95783612fcc61042a612fd49585848651166130cf565b169052612fff565b169052565b5050505050565b612ff9915060203d6020116104f3576104e4818361158b565b5f612f9c565b6001600160801b0390818111613013571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b8115613050570490565b613032565b90808202905f19818409908280831092039180830392146130c45761271090828211156130b2577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f198482099383808610950394808603951461314257848311156130b257829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b505090610a269250613046565b908160609103126103305780519160406020830151920151610a2681610536565b81835290916001600160fb1b0383116103305760209260051b809284830137010190565b90602082528035602083015260208101358060130b80910361033057604083015260408101356131c381610525565b6001600160a01b031660608381019190915281013536829003601e19018112156103305701602081359101906001600160401b038111610330578060051b360382136103305760a083608080610a269601520191613170565b9190915f8382019384129112908015821691151617611aae57565b6040516325f56f1160e01b81526001600160a01b039291606090829081906132629060048301613194565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104fa575f915f905f95613388575b50841561333557816132ac612624565b16917f000000000000000000000000000000000000000000000000000000000000000016821461332e57509060205f92600460405180958193634641257d60e01b83525af19081156104fa57613309925f9261330d575b5061321c565b9190565b61332791925060203d6020116104f3576104e4818361158b565b905f613303565b908161333b575b50509190565b803b1561033057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104fa57613375575b80613335565b80610e266133829261155d565b5f61336f565b919450506133ae915060603d6060116133b6575b6133a6818361158b565b81019061314f565b93905f61329c565b503d61339c565b600160ff1b8114611aae575f0390565b6133dc611d5e60985460801c90565b5f82126134b357816133ed91612871565b906133fa610cdd83612fff565b61340f6065549161ffff8360a01c1690613055565b80156134ae57807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc353186865479361344d611d5e6098546001600160801b031690565b8061349857505061349390925b6001600160a01b03169161346e84846140a1565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613493926134a8920390846130cf565b9261345a565b505050565b61042a610cdd916134c66115b9946133bd565b906127f7565b609954906001600160801b0382169182156135c35760801c6135006134f182476127f7565b6134fa85612583565b906140ed565b9081156135bc5761351082613acd565b9384156135b4578261353c61293161042a6115b996610cdd96611d7a611dec61042a8d611c069a6127f7565b6135468187614153565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a161042a61359861358788612fff565b6098546001600160801b0316612538565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b6135d161423a565b156135d857565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91613656575b5061364457565b60405163e775715160e01b8152600490fd5b61366f915060203d60201161178457611775818361158b565b5f61363d565b908160a0910312610330578051916020820151916040810151916080606083015192015190565b6136a46142f6565b60408301516136b16142f6565b5f80546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf919081906136ff90826120fe565b0390a26020830151926137106142f6565b61271061ffff8516116137675761375f9361372d61375293613b5c565b6065805461ffff60a01b191660a09290921b61ffff60a01b1691909117905551614324565b61375a614354565b614375565b6115b96143a4565b604051638a81d3b360e01b8152600490fd5b6137816142f6565b61378a81613f9c565b6001600160a01b03165f818152610202602081905260409091205460ff1615156001146137f557815f5260205260405f20600160ff19825416179055604051600181527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3565b604051637d5bf36f60e11b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613845575b505061195557565b5f805160206149f18339815191525416141590505f8061383d565b9060405161386d8161153d565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613a18575b613a0b57836139d5575f5b609a5f526001600160a01b03166138ca5f805160206149d18339815191528601613860565b80519097906138e1906001600160a01b031661187f565b986139066138fa6020809b01516001600160601b031690565b6001600160601b031690565b9483811080156139cb575b6139b95791600193979a9561393061393c939488035b838c03906140ed565b809201988703916130cf565b019701938086118015906139af575b6139a457609a5f52829061396d5f805160206149d18339815191528701613860565b805190890151969992966001600160a01b03909116946001939261393c9290916001600160601b0390911690613930908803613927565b945050509250509190565b508185101561394b565b60405163e8722f8f60e01b8152600490fd5b50808b1115613911565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b03166138a5565b505093505050505f905f90565b50841561389a565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00916002835414613aa85760028355814710613a90575f918291829182916001600160a01b03165af1613a72612b08565b5015613a7e5760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b5f546001600160a01b031633036118ec57565b609854906001600160801b03821681158015613afc575b15613aef5750905090565b610a269260801c916130cf565b508015613ae4565b6098546001600160801b0381169082158015613b54575b15613b2557505090565b60801c90613b348282856130cf565b9282156130505709613b435790565b6001810180911115610a2657612524565b508115613b1b565b613b646135ea565b6001600160a01b03168015613bac57606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b90613bc882612a35565b613bd5604051918261158b565b8281528092613be6601f1991612a35565b0190602036910137565b906030116103305790603090565b906090116103305760300190606090565b9060b0116103305760900190602090565b90939293848311610330578411610330578101920390565b9015612af65790565b9190811015612af65760051b0190565b359060208110613c5f575090565b5f199060200360031b1b1690565b96959490612dfc93613c8e613c9c926060979560808c5260808c0191612a15565b9089820360208b0152611f92565b918783036040890152612a15565b906020610a269281815201906129fd565b916020610a26938181520191612a15565b9193929060d154925f925f90613ce181613bbe565b97613cea614664565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a10613d2b5750505050505050505050565b60b0613d3b910180998985613c20565b9960409a8d613d778d51613d5f602091828101906123af81611dab8c8a8d87612de4565b805191012091613d70858b8b613c41565b3590612ba2565b52613d828184613bf0565b9093613da2613d9c613d948584613bfe565b959093613c0f565b90613c51565b908a3b15610330578b8f5f93613dcd915196879485946304512a2360e31b8652888c60048801613c6d565b03816801bc16d674ec8000008d5af19384156104fa57613e2060018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298613e2c575b5097019e5192839283613cbb565b0390a101989097613d18565b80610e26613e399261155d565b5f613e12565b90613e4d94959392916146a5565b1490565b9192915f915b808310613e65575050501490565b909192613e80600191613e79868587613c41565b3590614921565b93019190613e57565b8160301161033057613d9c917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316613ec7614664565b90613ede613ed58486613bfe565b96909486613c0f565b94813b15610330576801bc16d674ec8000005f94613f4497604051988996879586946304512a2360e31b865260806004870152613f35613f228d60848901906129fd565b60031994858983030160248a0152611f92565b92868403016044870152612a15565b90606483015203925af19081156104fa577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261349392613f8d575b5060405191829182613caa565b613f969061155d565b5f613f80565b61020180546001600160a01b0319166001600160a01b03929092169182179055337fda2bcad4d57ac529886ff995d07bce191c08b5424c8f5824de6c73f90cc623d45f80a3565b9190613fed6135ea565b6001600160a01b038316908115610e3257801561408f5780614014611d5e60985460801c90565b019361401e6127b5565b851161407d57610cdd9461404091612eb761403885613b04565b978893612fff565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c90606090a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b6140aa82612fff565b609854906140c26001600160801b03918284166125da565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b90808210156127dd575090565b609a5490600160401b821015611558576001820180609a55821015612af657609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f805160206149d183398151915290910155565b9081158015614232575b61422057609a54806141ea57505f905b6001600160a01b03918216928301928310611aae578183116141ca576115b992916141b561419d6141c59361484c565b916141a66115ac565b94166001600160a01b03168452565b6001600160601b03166020830152565b6140fa565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b03169061416d565b604051632ec8835b60e21b8152600490fd5b50801561415d565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91614290575090565b610a26915060203d60201161178457611775818361158b565b60018060a01b03165f52609c60205260405f20908154818103908111611aae576142d39255612fff565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f80516020614a118339815191525460401c161561431257565b604051631afcd79f60e31b8152600490fd5b61432c6142f6565b8015614342576001810161433d5750565b609d55565b6040516331278a8760e01b8152600490fd5b61435c6142f6565b6801bc16d674ec80000061436e6127b5565b1061434257565b61437d6142f6565b6001600160a01b03168061438e5750565b61016a80546001600160a01b0319169091179055565b6143ac6142f6565b6143b46142f6565b6143bc6142f6565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca0034106143f5576125c83430613fe3565b60405163ea2559bb60e01b8152600490fd5b90816020910312610330575160ff811681036103305790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f94816144aa575b5061447057604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206149f18339815191528403614491576115b992935061487f565b604051632a87526960e21b815260048101859052602490fd5b6144c491955060203d6020116104f3576104e4818361158b565b935f61444a565b6001600160a01b0381165f908152610137602052604090206144ec906124ff565b906001600160801b0361450683516001600160801b031690565b1615614660576107da61453d9161451b6135ea565b61452484612f4f565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104fa576145a086936145ae926145da965f926146485750613055565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104fa575f93614629575b50501061461757565b604051633684c65960e01b8152600490fd5b614640929350803d106104f3576104e4818361158b565b905f8061460e565b61094c919250863d88116104f3576104e4818361158b565b5050565b604051600160f81b60208201525f60218201523060601b602c82015260208152610a268161153d565b5f198114611aae5760010190565b35610a2681610536565b92939190918051936146b78486612871565b6146c087612863565b03614702576146ce86613bbe565b945f8094885f965f5b82811061473a57505015915061471490505750505003614702576146fe915f190190612ba2565b5190565b604051631a8a024960e11b8152600490fd5b91955092935015905061472c5750506146fe90612b95565b6147369250613c38565b3590565b8a868610156147ed575061476c6147678261475e6147578961468d565b988c612ba2565b51955b87613c41565b61469b565b156147d2578a868610156147b1575061479d6001929361479561478e8861468d565b978b612ba2565b515b90614921565b6147a7828d612ba2565b5201908a916146d7565b9261479d906147cc846147c66001969161468d565b96612ba2565b51614797565b61479d60019293613e796147e58c61468d565b9b8d8b613c41565b9161476782614803836147c661476c959161468d565b5195614761565b609a548061481757505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031661187f565b6001600160601b0390818111614860571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b15614900575f805160206149f183398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156148e5576125c891614942565b5050346148ee57565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b81811015614935575f5260205260405f2090565b905f5260205260405f2090565b5f80610a2693602081519101845af4614959612b08565b9161497f565b61496761423a565b61496d57565b6040516389a1dc6360e01b8152600490fd5b906149945750805115613a7e57805190602001fd5b815115806149c7575b6149a5575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561499d56fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220b65b21247b3d0da849e2508eba27c779ad5d2fbc94ae7abbc6a25ce14aaea84a64736f6c63430008160033", + "deployedBytecode": "0x60806040526004361015610022575b3615610018575f80fd5b610020612f2f565b005b5f3560e01c806301e1d11414610321578063066055e01461031c57806307a2d13a146103175780630d392cd91461031257806318f729501461030d5780631a7ff55314610308578063201b9eb51461030357806322758a4a146102fe5780632999ad3f146102f95780632cdf7401146102f45780633229fa95146102ef57806333194c0a146102ea5780633a98ef39146102e5578063439fab91146102e057806343e82a79146102db57806346904840146102d65780634ec96b22146102d15780634f1ef286146102cc578063514e2708146102c757806352d1902d146102c257806353156f28146102bd57806354fd4d50146102b85780635c60da1b146102b35780635cfc1a51146102ae5780635dddf3a8146102a957806360d60e6e146102a457806372b410a81461029f57806376b58b901461029a5780637bde82f2146102955780637fd6f15c146102905780638697d2c21461028b5780638ceab9aa146102865780639b401cde14610281578063a1bf49aa1461027c578063a49a1e7d14610277578063aaa4e83614610272578063ac9650d81461026d578063ad3cb1cc14610268578063c6e6f59214610263578063d83ad00c1461025e578063e74b981b14610259578063ef2a215814610254578063f04da65b1461024f578063f5e9de4d1461024a578063f6a6830f14610245578063f851a44014610240578063f9609f081461023b5763f98f5b920361000e576124b8565b61248e565b612467565b612426565b612296565b61225b565b6121d3565b612198565b612172565b612154565b61210f565b61201a565b611ed4565b611e7d565b611e60565b611e43565b611cfd565b611cd8565b611cb4565b611b91565b611b40565b611ab3565b611a0e565b6119f4565b6119da565b6119a6565b61198b565b611967565b6118fe565b611892565b61160c565b6114b3565b61148b565b61104c565b610f33565b610ec4565b610e8a565b610e5e565b610e44565b610a29565b6109d4565b6106a7565b610674565b61061d565b610540565b6104ff565b610354565b610334565b5f91031261033057565b5f80fd5b34610330575f36600319011261033057602060985460801c604051908152f35b34610330576020366003190112610330576001600160801b036004358181169081810361033057604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156104fa575f936104c9575b50335f908152610137602052604090206103f8906124ff565b9361040a85516001600160801b031690565b16156104b7578361044c61043f61042f6104659461042a6104b399612f4f565b612fff565b83516001600160801b0316612538565b6001600160801b03168252565b335f90815261013760205260409020612551565b612551565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104ec91935060203d6020116104f3575b6104e4818361158b565b8101906124e5565b915f6103df565b503d6104da565b6124f4565b3461033057602036600319011261033057602061051d600435612583565b604051908152f35b6001600160a01b0381160361033057565b8015150361033057565b34610330576040806003193601126103305760043561055e81610525565b6024359061056b82610536565b610201546001600160a01b039190821633036105fe571691825f52610202918260205260ff825f2054169281151580941515146105ed57906105c191855f52602052825f209060ff801983541691151516179055565b519081527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3005b8251637d5bf36f60e11b8152600490fd5b8351634ca8886760e01b8152600490fd5b908160809103126103305790565b60603660031901126103305760043561063581610525565b60243561064181610525565b604435906001600160401b0382116103305760209261066f61066a61051d94369060040161060f565b6125a9565b612e18565b34610330576020366003190112610330576004356001600160401b0381116103305761066a61002091369060040161060f565b346103305760603660031901126103305760048035906106c682610525565b60243590604435926106d784610525565b6106df6135c9565b6106e76135ea565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104fa575f986109b5575b50335f908152610137602052604090208390610770906124ff565b946001600160801b0361078a87516001600160801b031690565b16156109535761079986612f4f565b6107c56107b86107a889612fff565b88516001600160801b03166125da565b6001600160801b03168752565b335f908152609c6020526040902084906107e0905b54612583565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104fa5761086f928592610833925f92610934575b50613055565b9261084587516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104fa575f93610915575b5050106109075750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916108ce6104b3976104603360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b61092c929350803d106104f3576104e4818361158b565b905f80610881565b61094c919250843d86116104f3576104e4818361158b565b905f61082d565b885163752a536d60e01b8152915083828681865afa80156104fa576109846109939187945f91610998575b50612fff565b6001600160801b031687860152565b610799565b6109af9150873d89116104f3576104e4818361158b565b5f61097e565b6109cd919850823d84116104f3576104e4818361158b565b965f610755565b34610330575f36600319011261033057610201546040516001600160a01b039091168152602090f35b60609060031901126103305760043590602435610a1981610525565b90604435610a2681610525565b90565b3461033057610a37366109fd565b906001600160a01b0380831615610e3257610a506135ea565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156103305760408051631d8557d760e01b815260049491905f81878183875af180156104fa57610e19575b506001600160a01b0383165f90815261013760205260409020610ac3906124ff565b6001600160801b03610adc82516001600160801b031690565b1615610e0957610aeb81612f4f565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104fa57610b5a975f955f91610dd0575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104fa57610b75925f91610db35750613055565b95610b936107da8960018060a01b03165f52609c60205260405f2090565b918288118015610da3575b610d9357908a610bdb92610bb988516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104fa57670de0b6b3a764000093610c17938d5f94610d6a575b5050610c0b610c1191612c7e565b92612c9b565b916130cf565b1015610d5c578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104fa577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610d3995610cb193610d3e575b5050610c9461043f61042f8c612fff565b6001600160a01b0386165f90815261013760205260409020612551565b610cba82613acd565b90610cf8610cdd610cca85612fff565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610d0282866142a9565b610d0c8389613a20565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610d5492903d106104f3576104e4818361158b565b505f80610c83565b835163185cfc6d60e11b8152fd5b610c11929450610c0b9181610d8a92903d106104f3576104e4818361158b565b9391508d610bfd565b865163efda1a2760e01b81528490fd5b50610dac6125f5565b8811610b9e565b610dca91508c8d3d106104f3576104e4818361158b565b5f61082d565b9050610df591955060a03d60a011610e02575b610ded818361158b565b810190613675565b509692509050945f610b36565b503d610de3565b815163673f032f60e11b81528690fd5b80610e26610e2c9261155d565b80610326565b5f610aa1565b60405163d92e233d60e01b8152600490fd5b34610330575f36600319011261033057602061051d6125f5565b34610330575f366003190112610330576020610e78612624565b6040516001600160a01b039091168152f35b34610330575f3660031901126103305760206040517fa90b5863127e5f962890f832f07b9f40c8df2fc043326a0e4b538552d600f2d98152f35b34610330575f3660031901126103305760206001600160801b0360985416604051908152f35b906020600319830112610330576004356001600160401b039283821161033057806023830112156103305781600401359384116103305760248483010111610330576024019190565b610f3c36610eea565b905f80516020614a1183398151915254916001600160401b0360ff8460401c1615931680159081611044575b600114908161103a575b159081611031575b5061101f575f80516020614a11833981519152805467ffffffffffffffff19166001179055610fad9183610ffb576126f3565b610fb357005b5f80516020614a11833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f80516020614a11833981519152805460ff60401b1916600160401b1790556126f3565b60405163f92ee8a960e01b8152600490fd5b9050155f610f7a565b303b159150610f72565b849150610f68565b346103305761105a366109fd565b906001600160a01b039081831615610e32576110746135ea565b817f000000000000000000000000000000000000000000000000000000000000000016803b156103305760408051631d8557d760e01b815260049291905f81858183875af180156104fa57611478575b506001600160a01b0384165f908152610137602052604090206110e6906124ff565b926001600160801b0361110085516001600160801b031690565b161561146a5761110f84612f4f565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104fa575f955f9561143c575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104fa575f9961141d575b506001600160a01b038a165f908152609c602052604090206111ae906107da565b90818a11801561140d575b6113fd576111f490866111d387516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104fa575f926113dc575b506112129192613055565b116113cc578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104fa5785926113af575b5061125b8d612fff565b84516001600160801b03169061127091612538565b6001600160801b031684526001600160a01b038a165f908152610137602052604090208461129d91612551565b6112a689613acd565b976112b08a612fff565b60985460801c036001600160801b03166112df906001600160801b036098549181199060801b16911617609855565b6112e9898c6142a9565b6001600160a01b038b165f908152609c602052604090205461130a90612583565b9061131491613055565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104fa575f93611390575b505011611382575091610d39917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610d0c8389613a20565b9051631d8fa13d60e31b8152fd5b6113a7929350803d106104f3576104e4818361158b565b905f80611347565b6113c590833d85116104f3576104e4818361158b565b505f611251565b855163324b20e160e11b81528590fd5b61121292506113f790883d8a116104f3576104e4818361158b565b91611207565b875163efda1a2760e01b81528790fd5b506114166125f5565b8a116111b9565b611435919950853d87116104f3576104e4818361158b565b975f61118d565b61117a92965061145c91955060a03d60a011610e0257610ded818361158b565b505050959095949091611156565b905163673f032f60e11b8152fd5b80610e266114859261155d565b5f6110c4565b34610330575f366003190112610330576065546040516001600160a01b039091168152602090f35b34610330576020366003190112610330576004356114d081610525565b60018060a01b03165f52610137602052602060405f20604051906114f38261153d565b54906001600160801b03918281169081835260801c8483015261151b575b5116604051908152f35b61152481612f4f565b611511565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761155857604052565b611529565b6001600160401b03811161155857604052565b606081019081106001600160401b0382111761155857604052565b90601f801991011681019081106001600160401b0382111761155857604052565b604051906115b98261153d565b565b6001600160401b03811161155857601f01601f191660200190565b9291926115e2826115bb565b916115f0604051938461158b565b829481845281830111610330578281602093845f960137010152565b60408060031936011261033057600490813561162781610525565b6024356001600160401b03811161033057366023820112156103305761165690369060248187013591016115d6565b9161165f613807565b8051926116968461168860209363439fab9160e01b858401528460248401526044830190611f92565b03601f19810186528561158b565b61169e613807565b6116a6613aba565b6001600160a01b0383811680159291908790841561185d575b84156117ef575b841561178b575b505082156116f5575b50506116e6576100208383614420565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104fa575f9261175e575b5050155f806116d6565b61177d9250803d10611784575b611775818361158b565b8101906127e2565b5f80611754565b503d61176b565b855163054fd4d560e41b81529294508391839182905afa9081156104fa5760029160ff915f916117c2575b5016141591865f6116cd565b6117e29150843d86116117e8575b6117da818361158b565b810190614407565b5f6117b6565b503d6117d0565b935050835163198ca60560e11b815282818981875afa9081156104fa5788917fa90b5863127e5f962890f832f07b9f40c8df2fc043326a0e4b538552d600f2d9915f91611840575b501415936116c6565b6118579150853d87116104f3576104e4818361158b565b5f611837565b5f805160206149f183398151915254909450849061188b906001600160a01b03165b6001600160a01b031690565b14936116bf565b34610330576020366003190112610330576004356001600160a01b036118b66127c3565b1633036118ec578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b34610330575f366003190112610330577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036119555760206040515f805160206149f18339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f366003190112610330576001600160a01b03611982612624565b1633036118ec57005b34610330575f36600319011261033057602060405160018152f35b34610330575f366003190112610330575f805160206149f1833981519152546040516001600160a01b039091168152602090f35b34610330575f36600319011261033057602061051d6127b5565b34610330575f366003190112610330576020610e786127c3565b3461033057602036600319011261033057609a80549081905f6004355b848210611a5c57505050811015611a51576104b3905b6040519081529081906020820190565b506104b35f19611a41565b909193808316906001818518811c8301809311611aae575f8790525f805160206149d18339815191528301546001600160a01b0316841015611aa3575050935b9190611a2b565b909591019250611a9c565b612524565b34610330575f36600319011261033057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104fa576020915f91611b23575b506040519015158152f35b611b3a9150823d841161178457611775818361158b565b5f611b18565b34610330576080366003190112610330576104b3611b74600435611b6381610525565b606435906044359060243590612804565b604080519384526020840192909252908201529081906060820190565b34610330576040806003193601126103305760043560243591611bb383610525565b611bbb61495f565b8115611ca4576001600160a01b0383168015611c9357611bda83612583565b928315611c8257611be96125f5565b8411611c7157611c20846104b396611c11610cdd611c0684612fff565b60985460801c612538565b611c1b84336142a9565b613a20565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611c63336144cb565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b34610330575f36600319011261033057602061ffff60655460a01c16604051908152f35b34610330576060366003190112610330576104b3611b7460443560243560043561287e565b3461033057604080600319360112610330576004359060243590611d2082610525565b611d286135c9565b8215611ca4576001600160a01b0382168015611c935783611e08611dec6104b396611d6a611d5e6099546001600160801b031690565b6001600160801b031690565b81611dca611d7f83611d7a61480a565b612871565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611db981608081015b03601f19810183528261158b565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611de48382546127f7565b905501612fff565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611c57565b34610330575f36600319011261033057602060d054604051908152f35b34610330575f36600319011261033057602060d154604051908152f35b3461033057611ecf7f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611eaf36610eea565b9290611eb9613aba565b6040519182916020835233956020840191612a15565b0390a2005b3461033057602036600319011261033057600435611ef181610525565b611ef9613aba565b6001600160a01b03168015610e325760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f84011215610330578235916001600160401b038311610330576020808501948460051b01011161033057565b5f5b838110611f825750505f910152565b8181015183820152602001611f73565b90602091611fab81518092818552858086019101611f71565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611fec5750505050505090565b909192939495848061200a600193603f198682030187528a51611f92565b9801930193019194939290611fdc565b3461033057602036600319011261033057600480356001600160401b0381116103305761204b903690600401611f41565b9161205583612a4c565b925f5b81811061206d57604051806104b38782611fb7565b5f8061207a838588612adb565b6040939161208c855180938193612afb565b0390305af49061209a612b08565b91156120c15750906001916120af8288612ba2565b526120ba8187612ba2565b5001612058565b84826044815110610330576120e581836120fa930151602480918301019101612b37565b925162461bcd60e51b815292839283016120fe565b0390fd5b906020610a26928181520190611f92565b34610330575f366003190112610330576104b360405161212e8161153d565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611f92565b3461033057602036600319011261033057602061051d600435613acd565b34610330575f3660031901126103305760206001600160801b0360995416604051908152f35b34610330576020366003190112610330576100206004356121b881610525565b6121c0613aba565b613b5c565b908160a09103126103305790565b34610330576080366003190112610330576001600160401b03600435818111610330576122049036906004016121c5565b6024358281116103305761221c903690600401611f41565b60449291923584811161033057612237903690600401611f41565b9160643595861161033057612253610020963690600401611f41565b959094612cb2565b346103305760203660031901126103305760043561227881610525565b60018060a01b03165f52609c602052602060405f2054604051908152f35b3461033057604080600319360112610330576004906001600160401b038235818111610330576122c990369085016121c5565b90602435908111610330576122e19036908501611f41565b9390926122ec6135ea565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610330575f8251809263837d444160e01b825281838161233b8a8a8301612be7565b03925af180156104fa57612413575b506801bc16d674ec80000061235d6125f5565b10612406578083019360b06123728686612aa9565b9050036123f8576123c46123c89160d1549760d054906123b76123af8b6123998c8c612aa9565b611dab8b94929451938492602084019687612de4565b519020612e01565b6020815191012092613e51565b1590565b6123eb576100206001866123e56123df8888612aa9565b90613e89565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610e266124209261155d565b5f61234a565b346103305760203660031901126103305760043561244381610525565b60018060a01b03165f52610202602052602060ff60405f2054166040519015158152f35b34610330575f366003190112610330575f546040516001600160a01b039091168152602090f35b604036600319011261033057602061051d6004356124ab81610525565b6024359061066f82610525565b34610330576020366003190112610330576100206004356124d881610525565b6124e0613aba565b613f9c565b90816020910312610330575190565b6040513d5f823e3d90fd5b9060405161250c8161153d565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b039182169082160391908211611aae57565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b038116908161259b57505090565b91610a269260801c906130cf565b6125b290613237565b90806125cb575b506125c057565b6125c86134cc565b50565b6125d4906133cd565b5f6125b9565b9190916001600160801b0380809416911601918211611aae57565b4760995461260b6001600160801b038216612583565b9060801c01908181115f1461261e570390565b50505f90565b61016a546001600160a01b0316801561263a5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b908160209103126103305751610a2681610525565b906020828203126103305781356001600160401b039283821161033057019160608383031261033057604051926126aa84611570565b80358452602081013561ffff81168103610330576020850152604081013591821161033057019080601f83011215610330578160206126eb933591016115d6565b604082015290565b60405163e7f6f22560e01b815290916020908183600481335afa9283156104fa575f93612796575b50604051636f4fa30f60e01b8152938285600481335afa9081156104fa576115b99561275e945f93612763575b50506127579192810190612674565b908361369c565b613779565b6127579350908161278892903d1061278f575b612780818361158b565b81019061265f565b915f612748565b503d612776565b6127ae919350823d841161278f57612780818361158b565b915f61271b565b609d5480610a2657505f1990565b60d2546001600160a01b03908116806127dd57505f541690565b905090565b908160209103126103305751610a2681610536565b91908203918211611aae57565b604080516001600160a01b03909216602083019081529082019390935260608101829052909261285492909161283d8160808101611dab565b5190205f52609b60205260405f2054928391613885565b9091828103908111611aae5792565b9060018201809211611aae57565b91908201809211611aae57565b929190915f936128ae7f000000000000000000000000000000000000000000000000000000000000000085612871565b42106129eb5760408051336020820190815291810186905260608082018490528152601f19916128ef916128e360808261158b565b51902094868433612804565b90969095878781156129dd5750505f908152609b602052604081205560018211612993575b50505061294c61293161292685612fff565b60995460801c612538565b6001600160801b036099549181199060801b16911617609955565b6129568333613a20565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b6129d4919297506129a48785612871565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611db9908261158b565b555f8080612914565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116115585760051b60200190565b90612a5682612a35565b612a63604051918261158b565b8281528092612a74601f1991612a35565b01905f5b828110612a8457505050565b806060602080938501015201612a78565b634e487b7160e01b5f52603260045260245ffd5b903590601e198136030182121561033057018035906001600160401b0382116103305760200191813603831361033057565b90821015612af657612af29160051b810190612aa9565b9091565b612a95565b908092918237015f815290565b3d15612b32573d90612b19826115bb565b91612b27604051938461158b565b82523d5f602084013e565b606090565b602081830312610330578051906001600160401b038211610330570181601f82011215610330578051612b69816115bb565b92612b77604051948561158b565b8184526020828401011161033057610a269160208085019101611f71565b805115612af65760200190565b8051821015612af65760209160051b010190565b9035601e19823603018112156103305701602081359101916001600160401b03821161033057813603831361033057565b9060a0610a2692602081528235602082015260208301356040820152612c23612c136040850185612bb6565b84606085015260c0840191612a15565b90612c56612c4b612c376060870187612bb6565b601f19858703810160808701529591612a15565b946080810190612bb6565b93909282860301910152612a15565b906801bc16d674ec8000009180830292830403611aae57565b90670de0b6b3a764000091828102928184041490151715611aae57565b9061271091828102928184041490151715611aae57565b929094939195612cc06135ea565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b15610330576040965f8851809263837d444160e01b8252818381612d148c60048301612be7565b03925af180156104fa57612dd1575b50612d2c6125f5565b612d3589612c65565b11612dc05787158015612da6575b612d955791612d73959391612d6d896123c49795612d6760d054978c810190612aa9565b90613ccc565b94613e3f565b612d8557506115b99060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b50612db387860186612aa9565b905060b089021415612d43565b86516396d8043360e01b8152600490fd5b80610e26612dde9261155d565b5f612d23565b939291602091612dfc91604087526040870191612a15565b930152565b90604051916020830152602082526115b98261153d565b919091335f5261020260205260409260ff845f20541680612f14575b156105fe57612e416135ea565b6001600160a01b038216918215612f03573415612ef25734612e68611d5e60985460801c90565b0190612e726127b5565b8211612ee15794612ebc7f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c92610cdd9697612eb7612eaf34613b04565b988993612fff565b6140a1565b51348152602081018590526001600160a01b039290921660408301523391606090a390565b85516304ffa0ff60e51b8152600490fd5b84516318374fd160e21b8152600490fd5b845163d92e233d60e01b8152600490fd5b506001600160a01b0382165f9081528490205460ff16612e34565b335f5261020260205260ff60405f205416156118ec576125c83433613fe3565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91612fe0575b5060208201916001600160801b03918284511691828214612fd95783612fcc61042a612fd49585848651166130cf565b169052612fff565b169052565b5050505050565b612ff9915060203d6020116104f3576104e4818361158b565b5f612f9c565b6001600160801b0390818111613013571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b8115613050570490565b613032565b90808202905f19818409908280831092039180830392146130c45761271090828211156130b2577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f198482099383808610950394808603951461314257848311156130b257829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b505090610a269250613046565b908160609103126103305780519160406020830151920151610a2681610536565b81835290916001600160fb1b0383116103305760209260051b809284830137010190565b90602082528035602083015260208101358060130b80910361033057604083015260408101356131c381610525565b6001600160a01b031660608381019190915281013536829003601e19018112156103305701602081359101906001600160401b038111610330578060051b360382136103305760a083608080610a269601520191613170565b9190915f8382019384129112908015821691151617611aae57565b6040516325f56f1160e01b81526001600160a01b039291606090829081906132629060048301613194565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104fa575f915f905f95613388575b50841561333557816132ac612624565b16917f000000000000000000000000000000000000000000000000000000000000000016821461332e57509060205f92600460405180958193634641257d60e01b83525af19081156104fa57613309925f9261330d575b5061321c565b9190565b61332791925060203d6020116104f3576104e4818361158b565b905f613303565b908161333b575b50509190565b803b1561033057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104fa57613375575b80613335565b80610e266133829261155d565b5f61336f565b919450506133ae915060603d6060116133b6575b6133a6818361158b565b81019061314f565b93905f61329c565b503d61339c565b600160ff1b8114611aae575f0390565b6133dc611d5e60985460801c90565b5f82126134b357816133ed91612871565b906133fa610cdd83612fff565b61340f6065549161ffff8360a01c1690613055565b80156134ae57807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc353186865479361344d611d5e6098546001600160801b031690565b8061349857505061349390925b6001600160a01b03169161346e84846140a1565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b613493926134a8920390846130cf565b9261345a565b505050565b61042a610cdd916134c66115b9946133bd565b906127f7565b609954906001600160801b0382169182156135c35760801c6135006134f182476127f7565b6134fa85612583565b906140ed565b9081156135bc5761351082613acd565b9384156135b4578261353c61293161042a6115b996610cdd96611d7a611dec61042a8d611c069a6127f7565b6135468187614153565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a161042a61359861358788612fff565b6098546001600160801b0316612538565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b6135d161423a565b156135d857565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91613656575b5061364457565b60405163e775715160e01b8152600490fd5b61366f915060203d60201161178457611775818361158b565b5f61363d565b908160a0910312610330578051916020820151916040810151916080606083015192015190565b6136a46142f6565b60408301516136b16142f6565b5f80546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf919081906136ff90826120fe565b0390a26020830151926137106142f6565b61271061ffff8516116137675761375f9361372d61375293613b5c565b6065805461ffff60a01b191660a09290921b61ffff60a01b1691909117905551614324565b61375a614354565b614375565b6115b96143a4565b604051638a81d3b360e01b8152600490fd5b6137816142f6565b61378a81613f9c565b6001600160a01b03165f818152610202602081905260409091205460ff1615156001146137f557815f5260205260405f20600160ff19825416179055604051600181527fd9c6c3eabe38e3b9a606a66358d8f225489216a59eeba66facefb7d91663526660203392a3565b604051637d5bf36f60e11b8152600490fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116308114918215613845575b505061195557565b5f805160206149f18339815191525416141590505f8061383d565b9060405161386d8161153d565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613a18575b613a0b57836139d5575f5b609a5f526001600160a01b03166138ca5f805160206149d18339815191528601613860565b80519097906138e1906001600160a01b031661187f565b986139066138fa6020809b01516001600160601b031690565b6001600160601b031690565b9483811080156139cb575b6139b95791600193979a9561393061393c939488035b838c03906140ed565b809201988703916130cf565b019701938086118015906139af575b6139a457609a5f52829061396d5f805160206149d18339815191528701613860565b805190890151969992966001600160a01b03909116946001939261393c9290916001600160601b0390911690613930908803613927565b945050509250509190565b508185101561394b565b60405163e8722f8f60e01b8152600490fd5b50808b1115613911565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b03166138a5565b505093505050505f905f90565b50841561389a565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00916002835414613aa85760028355814710613a90575f918291829182916001600160a01b03165af1613a72612b08565b5015613a7e5760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b5f546001600160a01b031633036118ec57565b609854906001600160801b03821681158015613afc575b15613aef5750905090565b610a269260801c916130cf565b508015613ae4565b6098546001600160801b0381169082158015613b54575b15613b2557505090565b60801c90613b348282856130cf565b9282156130505709613b435790565b6001810180911115610a2657612524565b508115613b1b565b613b646135ea565b6001600160a01b03168015613bac57606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b90613bc882612a35565b613bd5604051918261158b565b8281528092613be6601f1991612a35565b0190602036910137565b906030116103305790603090565b906090116103305760300190606090565b9060b0116103305760900190602090565b90939293848311610330578411610330578101920390565b9015612af65790565b9190811015612af65760051b0190565b359060208110613c5f575090565b5f199060200360031b1b1690565b96959490612dfc93613c8e613c9c926060979560808c5260808c0191612a15565b9089820360208b0152611f92565b918783036040890152612a15565b906020610a269281815201906129fd565b916020610a26938181520191612a15565b9193929060d154925f925f90613ce181613bbe565b97613cea614664565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a10613d2b5750505050505050505050565b60b0613d3b910180998985613c20565b9960409a8d613d778d51613d5f602091828101906123af81611dab8c8a8d87612de4565b805191012091613d70858b8b613c41565b3590612ba2565b52613d828184613bf0565b9093613da2613d9c613d948584613bfe565b959093613c0f565b90613c51565b908a3b15610330578b8f5f93613dcd915196879485946304512a2360e31b8652888c60048801613c6d565b03816801bc16d674ec8000008d5af19384156104fa57613e2060018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298613e2c575b5097019e5192839283613cbb565b0390a101989097613d18565b80610e26613e399261155d565b5f613e12565b90613e4d94959392916146a5565b1490565b9192915f915b808310613e65575050501490565b909192613e80600191613e79868587613c41565b3590614921565b93019190613e57565b8160301161033057613d9c917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316613ec7614664565b90613ede613ed58486613bfe565b96909486613c0f565b94813b15610330576801bc16d674ec8000005f94613f4497604051988996879586946304512a2360e31b865260806004870152613f35613f228d60848901906129fd565b60031994858983030160248a0152611f92565b92868403016044870152612a15565b90606483015203925af19081156104fa577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261349392613f8d575b5060405191829182613caa565b613f969061155d565b5f613f80565b61020180546001600160a01b0319166001600160a01b03929092169182179055337fda2bcad4d57ac529886ff995d07bce191c08b5424c8f5824de6c73f90cc623d45f80a3565b9190613fed6135ea565b6001600160a01b038316908115610e3257801561408f5780614014611d5e60985460801c90565b019361401e6127b5565b851161407d57610cdd9461404091612eb761403885613b04565b978893612fff565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c90606090a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b6140aa82612fff565b609854906140c26001600160801b03918284166125da565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b90808210156127dd575090565b609a5490600160401b821015611558576001820180609a55821015612af657609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f805160206149d183398151915290910155565b9081158015614232575b61422057609a54806141ea57505f905b6001600160a01b03918216928301928310611aae578183116141ca576115b992916141b561419d6141c59361484c565b916141a66115ac565b94166001600160a01b03168452565b6001600160601b03166020830152565b6140fa565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b03169061416d565b604051632ec8835b60e21b8152600490fd5b50801561415d565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104fa575f91614290575090565b610a26915060203d60201161178457611775818361158b565b60018060a01b03165f52609c60205260405f20908154818103908111611aae576142d39255612fff565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f80516020614a118339815191525460401c161561431257565b604051631afcd79f60e31b8152600490fd5b61432c6142f6565b8015614342576001810161433d5750565b609d55565b6040516331278a8760e01b8152600490fd5b61435c6142f6565b6801bc16d674ec80000061436e6127b5565b1061434257565b61437d6142f6565b6001600160a01b03168061438e5750565b61016a80546001600160a01b0319169091179055565b6143ac6142f6565b6143b46142f6565b6143bc6142f6565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca0034106143f5576125c83430613fe3565b60405163ea2559bb60e01b8152600490fd5b90816020910312610330575160ff811681036103305790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f94816144aa575b5061447057604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206149f18339815191528403614491576115b992935061487f565b604051632a87526960e21b815260048101859052602490fd5b6144c491955060203d6020116104f3576104e4818361158b565b935f61444a565b6001600160a01b0381165f908152610137602052604090206144ec906124ff565b906001600160801b0361450683516001600160801b031690565b1615614660576107da61453d9161451b6135ea565b61452484612f4f565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104fa576145a086936145ae926145da965f926146485750613055565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104fa575f93614629575b50501061461757565b604051633684c65960e01b8152600490fd5b614640929350803d106104f3576104e4818361158b565b905f8061460e565b61094c919250863d88116104f3576104e4818361158b565b5050565b604051600160f81b60208201525f60218201523060601b602c82015260208152610a268161153d565b5f198114611aae5760010190565b35610a2681610536565b92939190918051936146b78486612871565b6146c087612863565b03614702576146ce86613bbe565b945f8094885f965f5b82811061473a57505015915061471490505750505003614702576146fe915f190190612ba2565b5190565b604051631a8a024960e11b8152600490fd5b91955092935015905061472c5750506146fe90612b95565b6147369250613c38565b3590565b8a868610156147ed575061476c6147678261475e6147578961468d565b988c612ba2565b51955b87613c41565b61469b565b156147d2578a868610156147b1575061479d6001929361479561478e8861468d565b978b612ba2565b515b90614921565b6147a7828d612ba2565b5201908a916146d7565b9261479d906147cc846147c66001969161468d565b96612ba2565b51614797565b61479d60019293613e796147e58c61468d565b9b8d8b613c41565b9161476782614803836147c661476c959161468d565b5195614761565b609a548061481757505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031661187f565b6001600160601b0390818111614860571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b15614900575f805160206149f183398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156148e5576125c891614942565b5050346148ee57565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b81811015614935575f5260205260405f2090565b905f5260205260405f2090565b5f80610a2693602081519101845af4614959612b08565b9161497f565b61496761423a565b61496d57565b6040516389a1dc6360e01b8152600490fd5b906149945750805115613a7e57805190602001fd5b815115806149c7575b6149a5575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561499d56fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220b65b21247b3d0da849e2508eba27c779ad5d2fbc94ae7abbc6a25ce14aaea84a64736f6c63430008160033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/shared/artifacts/EthValidatorsRegistry.json b/test/shared/artifacts/EthValidatorsRegistry.json new file mode 100644 index 00000000..af66ce6c --- /dev/null +++ b/test/shared/artifacts/EthValidatorsRegistry.json @@ -0,0 +1,120 @@ +{ + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "withdrawal_credentials", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "amount", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "index", + "type": "bytes" + } + ], + "name": "DepositEvent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "pubkey", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "withdrawal_credentials", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "deposit_data_root", + "type": "bytes32" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "get_deposit_count", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "get_deposit_root", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b5060005b601f8110156101025760026021826020811061002c57fe5b01546021836020811061003b57fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106100925780518252601f199092019160209182019101610073565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156100d1573d6000803e3d6000fd5b5050506040513d60208110156100e657600080fd5b5051602160018301602081106100f857fe5b0155600101610014565b506118d680620001136000396000f3fe60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033" +} \ No newline at end of file diff --git a/test/shared/artifacts/EthVault.json b/test/shared/artifacts/EthVault.json new file mode 100644 index 00000000..e8ade253 --- /dev/null +++ b/test/shared/artifacts/EthVault.json @@ -0,0 +1,1596 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "EthVault", + "sourceName": "contracts/vaults/ethereum/EthVault.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_validatorsRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenVaultController", + "type": "address" + }, + { + "internalType": "address", + "name": "osTokenConfig", + "type": "address" + }, + { + "internalType": "address", + "name": "sharedMevEscrow", + "type": "address" + }, + { + "internalType": "uint256", + "name": "exitedAssetsClaimDelay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "CapacityExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimTooEarly", + "type": "error" + }, + { + "inputs": [], + "name": "Collateralized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCheckpointValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeePercent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHealthFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLtv", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPosition", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecurityDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShares", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidator", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidValidators", + "type": "error" + }, + { + "inputs": [], + "name": "LowLtv", + "type": "error" + }, + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleProofInvalidMultiproof", + "type": "error" + }, + { + "inputs": [], + "name": "NotCollateralized", + "type": "error" + }, + { + "inputs": [], + "name": "NotHarvested", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "RedemptionExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [], + "name": "UpgradeFailed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "CheckpointCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "ExitQueueEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnAssets", + "type": "uint256" + } + ], + "name": "ExitedAssetsClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "feeRecipient", + "type": "address" + } + ], + "name": "FeeRecipientUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "FeeSharesMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "keysManager", + "type": "address" + } + ], + "name": "KeysManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "MetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "OsTokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "receivedAssets", + "type": "uint256" + } + ], + "name": "OsTokenLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "OsTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "OsTokenRedeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "ValidatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "validatorsRoot", + "type": "bytes32" + } + ], + "name": "ValidatorsRootUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "osTokenShares", + "type": "uint128" + } + ], + "name": "burnOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "calculateExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "leftShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capacity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exitQueueIndex", + "type": "uint256" + } + ], + "name": "claimExitedAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "newPositionTicket", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "claimedAssets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "enterExitQueue", + "outputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feePercent", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + } + ], + "name": "getExitQueueIndex", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isStateUpdateRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "keysManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "liquidateOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "mintOsToken", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "osTokenPositions", + "outputs": [ + { + "internalType": "uint128", + "name": "shares", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveFromMevEscrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "osTokenShares", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "redeemOsToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keysManager_", + "type": "address" + } + ], + "name": "setKeysManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" + } + ], + "name": "setMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_validatorsRoot", + "type": "bytes32" + } + ], + "name": "setValidatorsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateStateAndDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawableAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x610180346200022657601f620049a438819003918201601f19168301926001600160401b03929091838511838610176200022a578160e09284926040978852833981010312620002265762000054816200023e565b9262000063602083016200023e565b90620000718184016200023e565b9362000080606085016200023e565b946200008f608086016200023e565b9360c0620000a060a088016200023e565b9601519760805260a05260c0523060e05261010095865260018060a01b038061012096168652610140931683526101609384527ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff82851c1662000215578080831603620001d0575b5050505192614750948562000254863960805185818161199e015281816121ae01528181612af801528181612f710152818161330e0152613f3f015260a051856115e4015260c0518581816139710152613b12015260e0518581816117d0015261348c015251846126bf01525183818161036f015281816106000152818161091301528181610f3701528181612c6d01526142c80152518281816106dc015281816109bf01528181610fe3015261424701525181818161248f0152612fb90152f35b6001600160401b0319909116811790915581519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80806200010e565b835163f92ee8a960e01b8152600490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203620002265756fe60806040526004361015610022575b3615610018575f80fd5b610020612c4e565b005b5f3560e01c806301e1d114146102e1578063066055e0146102dc57806307a2d13a146102d757806318f72950146102d25780631a7ff553146102cd578063201b9eb5146102c85780632999ad3f146102c35780632cdf7401146102be5780633229fa95146102b957806333194c0a146102b45780633a98ef39146102af578063439fab91146102aa57806343e82a79146102a557806346904840146102a05780634ec96b221461029b5780634f1ef28614610296578063514e27081461029157806352d1902d1461028c57806353156f281461028757806354fd4d50146102825780635c60da1b1461027d5780635cfc1a51146102785780635dddf3a81461027357806360d60e6e1461026e57806372b410a81461026957806376b58b90146102645780637bde82f21461025f5780637fd6f15c1461025a5780638697d2c2146102555780638ceab9aa146102505780639b401cde1461024b578063a1bf49aa14610246578063a49a1e7d14610241578063aaa4e8361461023c578063ac9650d814610237578063ad3cb1cc14610232578063c6e6f5921461022d578063d83ad00c14610228578063e74b981b14610223578063ef2a21581461021e578063f04da65b14610219578063f5e9de4d14610214578063f851a4401461020f5763f9609f080361000e5761230d565b6122e6565b612156565b61211b565b612093565b612058565b612032565b612014565b611fcf565b611eda565b611d94565b611d3d565b611d20565b611d03565b611bbd565b611b98565b611b74565b611a51565b611a00565b611973565b6118ce565b6118b4565b61189a565b611866565b61184b565b611827565b6117be565b611752565b6114cc565b611373565b61134b565b610f0c565b610df3565b610d84565b610d4a565b610d1e565b610d04565b6108e9565b610590565b61055d565b610504565b6104bf565b610314565b6102f4565b5f9103126102f057565b5f80fd5b346102f0575f3660031901126102f057602060985460801c604051908152f35b346102f05760203660031901126102f0576001600160801b03600435818116908181036102f057604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156104ba575f93610489575b50335f908152610137602052604090206103b890612351565b936103ca85516001600160801b031690565b1615610477578361040c6103ff6103ef610425946103ea61047399612c58565b612d08565b83516001600160801b031661238a565b6001600160801b03168252565b335f908152610137602052604090206123a3565b6123a3565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104ac91935060203d6020116104b3575b6104a4818361144b565b810190612337565b915f61039f565b503d61049a565b612346565b346102f05760203660031901126102f05760206104dd6004356123d5565b604051908152f35b6001600160a01b038116036102f057565b908160809103126102f05790565b60603660031901126102f05760043561051c816104e5565b602435610528816104e5565b604435906001600160401b0382116102f0576020926105566105516104dd9436906004016104f6565b6123fb565b3490613cdf565b346102f05760203660031901126102f0576004356001600160401b0381116102f0576105516100209136906004016104f6565b346102f05760603660031901126102f05760048035906105af826104e5565b60243590604435926105c0846104e5565b6105c86132d2565b6105d06132f3565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104ba575f9861089e575b50335f90815261013760205260409020839061065990612351565b946001600160801b0361067387516001600160801b031690565b161561083c5761068286612c58565b6106ae6106a161069189612d08565b88516001600160801b031661242c565b6001600160801b03168752565b335f908152609c6020526040902084906106c9905b546123d5565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104ba5761075892859261071c925f9261081d575b50612d5e565b9261072e87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104ba575f936107fe575b5050106107f05750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916107b7610473976104203360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610815929350803d106104b3576104a4818361144b565b905f8061076a565b610835919250843d86116104b3576104a4818361144b565b905f610716565b885163752a536d60e01b8152915083828681865afa80156104ba5761086d61087c9187945f91610881575b50612d08565b6001600160801b031687860152565b610682565b6108989150873d89116104b3576104a4818361144b565b5f610867565b6108b6919850823d84116104b3576104a4818361144b565b965f61063e565b60609060031901126102f057600435906024356108d9816104e5565b906044356108e6816104e5565b90565b346102f0576108f7366108bd565b906001600160a01b0380831615610cf2576109106132f3565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156102f05760408051631d8557d760e01b815260049491905f81878183875af180156104ba57610cd9575b506001600160a01b0383165f9081526101376020526040902061098390612351565b6001600160801b0361099c82516001600160801b031690565b1615610cc9576109ab81612c58565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104ba57610a1a975f955f91610c90575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104ba57610a35925f91610c735750612d5e565b95610a536106c38960018060a01b03165f52609c60205260405f2090565b918288118015610c63575b610c5357908a610a9b92610a7988516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104ba57670de0b6b3a764000093610ad7938d5f94610c2a575b5050610acb610ad191612ab4565b92612ad1565b91612dd8565b1015610c1c578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104ba577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610bf995610b7193610bfe575b5050610b546103ff6103ef8c612d08565b6001600160a01b0386165f908152610137602052604090206123a3565b610b7a82613748565b90610bb8610b9d610b8a85612d08565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610bc28286613f93565b610bcc838961369b565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610c1492903d106104b3576104a4818361144b565b505f80610b43565b835163185cfc6d60e11b8152fd5b610ad1929450610acb9181610c4a92903d106104b3576104a4818361144b565b9391508d610abd565b865163efda1a2760e01b81528490fd5b50610c6c612447565b8811610a5e565b610c8a91508c8d3d106104b3576104a4818361144b565b5f610716565b9050610cb591955060a03d60a011610cc2575b610cad818361144b565b81019061337e565b509692509050945f6109f6565b503d610ca3565b815163673f032f60e11b81528690fd5b80610ce6610cec9261141d565b806102e6565b5f610961565b60405163d92e233d60e01b8152600490fd5b346102f0575f3660031901126102f05760206104dd612447565b346102f0575f3660031901126102f0576020610d38612476565b6040516001600160a01b039091168152f35b346102f0575f3660031901126102f05760206040517fd92dbcef7ed61a67c0eefa7cafcc41f41d9402a5046486977364b4724c821f8b8152f35b346102f0575f3660031901126102f05760206001600160801b0360985416604051908152f35b9060206003198301126102f0576004356001600160401b03928382116102f057806023830112156102f05781600401359384116102f057602484830101116102f0576024019190565b610dfc36610daa565b905f805160206146fb83398151915254916001600160401b0360ff8460401c1615931680159081610f04575b6001149081610efa575b159081610ef1575b50610edf575f805160206146fb833981519152805467ffffffffffffffff19166001179055610e6d9183610ebb576124c6565b610e7357005b5f805160206146fb833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f805160206146fb833981519152805460ff60401b1916600160401b1790556124c6565b60405163f92ee8a960e01b8152600490fd5b9050155f610e3a565b303b159150610e32565b849150610e28565b346102f057610f1a366108bd565b906001600160a01b039081831615610cf257610f346132f3565b817f000000000000000000000000000000000000000000000000000000000000000016803b156102f05760408051631d8557d760e01b815260049291905f81858183875af180156104ba57611338575b506001600160a01b0384165f90815261013760205260409020610fa690612351565b926001600160801b03610fc085516001600160801b031690565b161561132a57610fcf84612c58565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104ba575f955f956112fc575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104ba575f996112dd575b506001600160a01b038a165f908152609c6020526040902061106e906106c3565b90818a1180156112cd575b6112bd576110b4908661109387516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104ba575f9261129c575b506110d29192612d5e565b1161128c578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104ba57859261126f575b5061111b8d612d08565b84516001600160801b0316906111309161238a565b6001600160801b031684526001600160a01b038a165f908152610137602052604090208461115d916123a3565b61116689613748565b976111708a612d08565b60985460801c036001600160801b031661119f906001600160801b036098549181199060801b16911617609855565b6111a9898c613f93565b6001600160a01b038b165f908152609c60205260409020546111ca906123d5565b906111d491612d5e565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104ba575f93611250575b505011611242575091610bf9917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610bcc838961369b565b9051631d8fa13d60e31b8152fd5b611267929350803d106104b3576104a4818361144b565b905f80611207565b61128590833d85116104b3576104a4818361144b565b505f611111565b855163324b20e160e11b81528590fd5b6110d292506112b790883d8a116104b3576104a4818361144b565b916110c7565b875163efda1a2760e01b81528790fd5b506112d6612447565b8a11611079565b6112f5919950853d87116104b3576104a4818361144b565b975f61104d565b61103a92965061131c91955060a03d60a011610cc257610cad818361144b565b505050959095949091611016565b905163673f032f60e11b8152fd5b80610ce66113459261141d565b5f610f84565b346102f0575f3660031901126102f0576065546040516001600160a01b039091168152602090f35b346102f05760203660031901126102f057600435611390816104e5565b60018060a01b03165f52610137602052602060405f20604051906113b3826113fd565b54906001600160801b03918281169081835260801c848301526113db575b5116604051908152f35b6113e481612c58565b6113d1565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761141857604052565b6113e9565b6001600160401b03811161141857604052565b606081019081106001600160401b0382111761141857604052565b90601f801991011681019081106001600160401b0382111761141857604052565b60405190611479826113fd565b565b6001600160401b03811161141857601f01601f191660200190565b9291926114a28261147b565b916114b0604051938461144b565b8294818452818301116102f0578281602093845f960137010152565b6040806003193601126102f05760049081356114e7816104e5565b6024356001600160401b0381116102f057366023820112156102f0576115169036906024818701359101611496565b9161151f613482565b8051926115568461154860209363439fab9160e01b858401528460248401526044830190611e52565b03601f19810186528561144b565b61155e613482565b611566613735565b6001600160a01b0383811680159291908790841561171d575b84156116af575b841561164b575b505082156115b5575b50506115a657610020838361410a565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104ba575f9261161e575b5050155f80611596565b61163d9250803d10611644575b611635818361144b565b810190612618565b5f80611614565b503d61162b565b855163054fd4d560e41b81529294508391839182905afa9081156104ba5760029160ff915f91611682575b5016141591865f61158d565b6116a29150843d86116116a8575b61169a818361144b565b8101906140f1565b5f611676565b503d611690565b935050835163198ca60560e11b815282818981875afa9081156104ba5788917fd92dbcef7ed61a67c0eefa7cafcc41f41d9402a5046486977364b4724c821f8b915f91611700575b50141593611586565b6117179150853d87116104b3576104a4818361144b565b5f6116f7565b5f805160206146db83398151915254909450849061174b906001600160a01b03165b6001600160a01b031690565b149361157f565b346102f05760203660031901126102f0576004356001600160a01b036117766125ef565b1633036117ac578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346102f0575f3660031901126102f0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036118155760206040515f805160206146db8339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126102f0576001600160a01b03611842612476565b1633036117ac57005b346102f0575f3660031901126102f057602060405160018152f35b346102f0575f3660031901126102f0575f805160206146db833981519152546040516001600160a01b039091168152602090f35b346102f0575f3660031901126102f05760206104dd6125e1565b346102f0575f3660031901126102f0576020610d386125ef565b346102f05760203660031901126102f057609a80549081905f6004355b84821061191c5750505081101561191157610473905b6040519081529081906020820190565b506104735f19611901565b909193808316906001818518811c830180931161196e575f8790525f805160206146bb8339815191528301546001600160a01b0316841015611963575050935b91906118eb565b90959101925061195c565b612376565b346102f0575f3660031901126102f057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104ba576020915f916119e3575b506040519015158152f35b6119fa9150823d841161164457611635818361144b565b5f6119d8565b346102f05760803660031901126102f057610473611a34600435611a23816104e5565b60643590604435906024359061263a565b604080519384526020840192909252908201529081906060820190565b346102f0576040806003193601126102f05760043560243591611a73836104e5565b611a7b614649565b8115611b64576001600160a01b0383168015611b5357611a9a836123d5565b928315611b4257611aa9612447565b8411611b3157611ae08461047396611ad1610b9d611ac684612d08565b60985460801c61238a565b611adb8433613f93565b61369b565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611b23336141b5565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346102f0575f3660031901126102f057602061ffff60655460a01c16604051908152f35b346102f05760603660031901126102f057610473611a346044356024356004356126b4565b346102f0576040806003193601126102f0576004359060243590611be0826104e5565b611be86132d2565b8215611b64576001600160a01b0382168015611b535783611cc8611cac61047396611c2a611c1e6099546001600160801b031690565b6001600160801b031690565b81611c8a611c3f83611c3a6144f4565b6126a7565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611c7981608081015b03601f19810183528261144b565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611ca483825461262d565b905501612d08565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611b17565b346102f0575f3660031901126102f057602060d054604051908152f35b346102f0575f3660031901126102f057602060d154604051908152f35b346102f057611d8f7f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611d6f36610daa565b9290611d79613735565b604051918291602083523395602084019161284b565b0390a2005b346102f05760203660031901126102f057600435611db1816104e5565b611db9613735565b6001600160a01b03168015610cf25760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156102f0578235916001600160401b0383116102f0576020808501948460051b0101116102f057565b5f5b838110611e425750505f910152565b8181015183820152602001611e33565b90602091611e6b81518092818552858086019101611e31565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611eac5750505050505090565b9091929394958480611eca600193603f198682030187528a51611e52565b9801930193019194939290611e9c565b346102f05760203660031901126102f057600480356001600160401b0381116102f057611f0b903690600401611e01565b91611f1583612882565b925f5b818110611f2d57604051806104738782611e77565b5f80611f3a838588612911565b60409391611f4c855180938193612931565b0390305af490611f5a61293e565b9115611f81575090600191611f6f82886129d8565b52611f7a81876129d8565b5001611f18565b848260448151106102f057611fa58183611fba93015160248091830101910161296d565b925162461bcd60e51b81529283928301611fbe565b0390fd5b9060206108e6928181520190611e52565b346102f0575f3660031901126102f057610473604051611fee816113fd565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611e52565b346102f05760203660031901126102f05760206104dd600435613748565b346102f0575f3660031901126102f05760206001600160801b0360995416604051908152f35b346102f05760203660031901126102f057610020600435612078816104e5565b612080613735565b6137d7565b908160a09103126102f05790565b346102f05760803660031901126102f0576001600160401b036004358181116102f0576120c4903690600401612085565b6024358281116102f0576120dc903690600401611e01565b6044929192358481116102f0576120f7903690600401611e01565b916064359586116102f057612113610020963690600401611e01565b959094612ae8565b346102f05760203660031901126102f057600435612138816104e5565b60018060a01b03165f52609c602052602060405f2054604051908152f35b346102f0576040806003193601126102f0576004906001600160401b0382358181116102f0576121899036908501612085565b906024359081116102f0576121a19036908501611e01565b9390926121ac6132f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156102f0575f8251809263837d444160e01b82528183816121fb8a8a8301612a1d565b03925af180156104ba576122d3575b506801bc16d674ec80000061221d612447565b106122c6578083019360b061223286866128df565b9050036122b8576122846122889160d1549760d0549061227761226f8b6122598c8c6128df565b611c6b8b94929451938492602084019687612c1a565b519020612c37565b6020815191012092613acc565b1590565b6122ab576100206001866122a561229f88886128df565b90613b04565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610ce66122e09261141d565b5f61220a565b346102f0575f3660031901126102f0575f546040516001600160a01b039091168152602090f35b60403660031901126102f05760206104dd60043561232a816104e5565b60243590610556826104e5565b908160209103126102f0575190565b6040513d5f823e3d90fd5b9060405161235e816113fd565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b03918216908216039190821161196e57565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b03811690816123ed57505090565b916108e69260801c90612dd8565b61240490612f40565b908061241d575b5061241257565b61241a6131d5565b50565b612426906130d6565b5f61240b565b9190916001600160801b038080941691160191821161196e57565b4760995461245d6001600160801b0382166123d5565b9060801c01908181115f14612470570390565b50505f90565b61016a546001600160a01b0316801561248c5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b908160209103126102f057516108e6816104e5565b60405163e7f6f22560e01b8152602092908381600481335afa9081156104ba575f916125c4575b50604051636f4fa30f60e01b8152918483600481335afa9283156104ba575f93612595575b5083019380848603126102f05783356001600160401b03948582116102f05701936060858703126102f0576040519461254a86611430565b803586528281013561ffff811681036102f0578387015260408101359182116102f057019480601f870112156102f0578561258b9261147997359101611496565b60408401526133a5565b6125b6919350853d87116125bd575b6125ae818361144b565b8101906124b1565b915f612512565b503d6125a4565b6125db9150843d86116125bd576125ae818361144b565b5f6124ed565b609d54806108e657505f1990565b60d2546001600160a01b039081168061260957505f541690565b905090565b801515036102f057565b908160209103126102f057516108e68161260e565b9190820391821161196e57565b604080516001600160a01b03909216602083019081529082019390935260608101829052909261268a9290916126738160808101611c6b565b5190205f52609b60205260405f2054928391613500565b909182810390811161196e5792565b906001820180921161196e57565b9190820180921161196e57565b929190915f936126e47f0000000000000000000000000000000000000000000000000000000000000000856126a7565b42106128215760408051336020820190815291810186905260608082018490528152601f19916127259161271960808261144b565b5190209486843361263a565b90969095878781156128135750505f908152609b6020526040812055600182116127c9575b50505061278261276761275c85612d08565b60995460801c61238a565b6001600160801b036099549181199060801b16911617609955565b61278c833361369b565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b61280a919297506127da87856126a7565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611c79908261144b565b555f808061274a565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116114185760051b60200190565b9061288c8261286b565b612899604051918261144b565b82815280926128aa601f199161286b565b01905f5b8281106128ba57505050565b8060606020809385010152016128ae565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156102f057018035906001600160401b0382116102f0576020019181360383136102f057565b9082101561292c576129289160051b8101906128df565b9091565b6128cb565b908092918237015f815290565b3d15612968573d9061294f8261147b565b9161295d604051938461144b565b82523d5f602084013e565b606090565b6020818303126102f0578051906001600160401b0382116102f0570181601f820112156102f057805161299f8161147b565b926129ad604051948561144b565b818452602082840101116102f0576108e69160208085019101611e31565b80511561292c5760200190565b805182101561292c5760209160051b010190565b9035601e19823603018112156102f05701602081359101916001600160401b0382116102f05781360383136102f057565b9060a06108e692602081528235602082015260208301356040820152612a59612a4960408501856129ec565b84606085015260c084019161284b565b90612a8c612a81612a6d60608701876129ec565b601f1985870381016080870152959161284b565b9460808101906129ec565b9390928286030191015261284b565b906801bc16d674ec800000918083029283040361196e57565b90670de0b6b3a76400009182810292818404149015171561196e57565b906127109182810292818404149015171561196e57565b929094939195612af66132f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156102f0576040965f8851809263837d444160e01b8252818381612b4a8c60048301612a1d565b03925af180156104ba57612c07575b50612b62612447565b612b6b89612a9b565b11612bf65787158015612bdc575b612bcb5791612ba9959391612ba3896122849795612b9d60d054978c8101906128df565b90613947565b94613aba565b612bbb57506114799060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b50612be9878601866128df565b905060b089021415612b79565b86516396d8043360e01b8152600490fd5b80610ce6612c149261141d565b5f612b59565b939291602091612c329160408752604087019161284b565b930152565b9060405191602083015260208252611479826113fd565b61241a3433613c17565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f91612ce9575b5060208201916001600160801b03918284511691828214612ce25783612cd56103ea612cdd958584865116612dd8565b169052612d08565b169052565b5050505050565b612d02915060203d6020116104b3576104a4818361144b565b5f612ca5565b6001600160801b0390818111612d1c571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b8115612d59570490565b612d3b565b90808202905f1981840990828083109203918083039214612dcd576127109082821115612dbb577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f1984820993838086109503948086039514612e4b5784831115612dbb57829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b5050906108e69250612d4f565b908160609103126102f057805191604060208301519201516108e68161260e565b81835290916001600160fb1b0383116102f05760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036102f05760408301526040810135612ecc816104e5565b6001600160a01b031660608381019190915281013536829003601e19018112156102f05701602081359101906001600160401b0381116102f0578060051b360382136102f05760a0836080806108e69601520191612e79565b9190915f838201938412911290801582169115161761196e57565b6040516325f56f1160e01b81526001600160a01b03929160609082908190612f6b9060048301612e9d565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104ba575f915f905f95613091575b50841561303e5781612fb5612476565b16917f000000000000000000000000000000000000000000000000000000000000000016821461303757509060205f92600460405180958193634641257d60e01b83525af19081156104ba57613012925f92613016575b50612f25565b9190565b61303091925060203d6020116104b3576104a4818361144b565b905f61300c565b9081613044575b50509190565b803b156102f057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104ba5761307e575b8061303e565b80610ce661308b9261141d565b5f613078565b919450506130b7915060603d6060116130bf575b6130af818361144b565b810190612e58565b93905f612fa5565b503d6130a5565b600160ff1b811461196e575f0390565b6130e5611c1e60985460801c90565b5f82126131bc57816130f6916126a7565b90613103610b9d83612d08565b6131186065549161ffff8360a01c1690612d5e565b80156131b757807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc3531868654793613156611c1e6098546001600160801b031690565b806131a157505061319c90925b6001600160a01b0316916131778484613d8b565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b61319c926131b192039084612dd8565b92613163565b505050565b6103ea610b9d916131cf611479946130c6565b9061262d565b609954906001600160801b0382169182156132cc5760801c6132096131fa824761262d565b613203856123d5565b90613dd7565b9081156132c55761321982613748565b9384156132bd57826132456127676103ea61147996610b9d96611c3a611cac6103ea8d611ac69a61262d565b61324f8187613e3d565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16103ea6132a161329088612d08565b6098546001600160801b031661238a565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b6132da613f24565b156132e157565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f9161335f575b5061334d57565b60405163e775715160e01b8152600490fd5b613378915060203d60201161164457611635818361144b565b5f613346565b908160a09103126102f0578051916020820151916040810151916080606083015192015190565b6133ad613fe0565b60408301516133ba613fe0565b5f80546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf919081906134089082611fbe565b0390a2602083015192613419613fe0565b61271061ffff851611613470576134689361343661345b936137d7565b6065805461ffff60a01b191660a09290921b61ffff60a01b169190911790555161400e565b61346361403e565b61405f565b61147961408e565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163081149182156134c0575b505061181557565b5f805160206146db8339815191525416141590505f806134b8565b906040516134e8816113fd565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613693575b6136865783613650575f5b609a5f526001600160a01b03166135455f805160206146bb83398151915286016134db565b805190979061355c906001600160a01b031661173f565b986135816135756020809b01516001600160601b031690565b6001600160601b031690565b948381108015613646575b6136345791600193979a956135ab6135b7939488035b838c0390613dd7565b80920198870391612dd8565b0197019380861180159061362a575b61361f57609a5f5282906135e85f805160206146bb83398151915287016134db565b805190890151969992966001600160a01b0390911694600193926135b79290916001600160601b03909116906135ab9088036135a2565b945050509250509190565b50818510156135c6565b60405163e8722f8f60e01b8152600490fd5b50808b111561358c565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b0316613520565b505093505050505f905f90565b508415613515565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00916002835414613723576002835581471061370b575f918291829182916001600160a01b03165af16136ed61293e565b50156136f95760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b5f546001600160a01b031633036117ac57565b609854906001600160801b03821681158015613777575b1561376a5750905090565b6108e69260801c91612dd8565b50801561375f565b6098546001600160801b03811690821580156137cf575b156137a057505090565b60801c906137af828285612dd8565b928215612d5957096137be5790565b60018101809111156108e657612376565b508115613796565b6137df6132f3565b6001600160a01b0316801561382757606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b906138438261286b565b613850604051918261144b565b8281528092613861601f199161286b565b0190602036910137565b906030116102f05790603090565b906090116102f05760300190606090565b9060b0116102f05760900190602090565b909392938483116102f05784116102f0578101920390565b901561292c5790565b919081101561292c5760051b0190565b3590602081106138da575090565b5f199060200360031b1b1690565b96959490612c3293613909613917926060979560808c5260808c019161284b565b9089820360208b0152611e52565b91878303604089015261284b565b9060206108e6928181520190612833565b9160206108e693818152019161284b565b9193929060d154925f925f9061395c81613839565b9761396561434e565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106139a65750505050505050505050565b60b06139b691018099898561389b565b9960409a8d6139f28d516139da6020918281019061226f81611c6b8c8a8d87612c1a565b8051910120916139eb858b8b6138bc565b35906129d8565b526139fd818461386b565b9093613a1d613a17613a0f8584613879565b95909361388a565b906138cc565b908a3b156102f0578b8f5f93613a48915196879485946304512a2360e31b8652888c600488016138e8565b03816801bc16d674ec8000008d5af19384156104ba57613a9b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298613aa7575b5097019e5192839283613936565b0390a101989097613993565b80610ce6613ab49261141d565b5f613a8d565b90613ac8949593929161438f565b1490565b9192915f915b808310613ae0575050501490565b909192613afb600191613af48685876138bc565b359061460b565b93019190613ad2565b816030116102f057613a17917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316613b4261434e565b90613b59613b508486613879565b9690948661388a565b94813b156102f0576801bc16d674ec8000005f94613bbf97604051988996879586946304512a2360e31b865260806004870152613bb0613b9d8d6084890190612833565b60031994858983030160248a0152611e52565b9286840301604487015261284b565b90606483015203925af19081156104ba577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261319c92613c08575b5060405191829182613925565b613c119061141d565b5f613bfb565b9190613c216132f3565b6001600160a01b038316908115610cf2578015613ccd5780613c48611c1e60985460801c90565b0193613c526125e1565b8511613cbb57610b9d94613c7991613c74613c6c8561377f565b978893612d08565b613d8b565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b90929192613ceb6132f3565b6001600160a01b038216918215610cf2578115613ccd5781613d12611c1e60985460801c90565b01613d1b6125e1565b8111613cbb57610b9d95613d62613cb6927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c94613c74613d5a8861377f565b9a8b93612d08565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b613d9482612d08565b60985490613dac6001600160801b039182841661242c565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b9080821015612609575090565b609a5490600160401b821015611418576001820180609a5582101561292c57609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f805160206146bb83398151915290910155565b9081158015613f1c575b613f0a57609a5480613ed457505f905b6001600160a01b0391821692830192831061196e57818311613eb4576114799291613e9f613e87613eaf93614536565b91613e9061146c565b94166001600160a01b03168452565b6001600160601b03166020830152565b613de4565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031690613e57565b604051632ec8835b60e21b8152600490fd5b508015613e47565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f91613f7a575090565b6108e6915060203d60201161164457611635818361144b565b60018060a01b03165f52609c60205260405f2090815481810390811161196e57613fbd9255612d08565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f805160206146fb8339815191525460401c1615613ffc57565b604051631afcd79f60e31b8152600490fd5b614016613fe0565b801561402c57600181016140275750565b609d55565b6040516331278a8760e01b8152600490fd5b614046613fe0565b6801bc16d674ec8000006140586125e1565b1061402c57565b614067613fe0565b6001600160a01b0316806140785750565b61016a80546001600160a01b0319169091179055565b614096613fe0565b61409e613fe0565b6140a6613fe0565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca0034106140df5761241a3430613c17565b60405163ea2559bb60e01b8152600490fd5b908160209103126102f0575160ff811681036102f05790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614194575b5061415a57604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206146db833981519152840361417b57611479929350614569565b604051632a87526960e21b815260048101859052602490fd5b6141ae91955060203d6020116104b3576104a4818361144b565b935f614134565b6001600160a01b0381165f908152610137602052604090206141d690612351565b906001600160801b036141f083516001600160801b031690565b161561434a576106c3614227916142056132f3565b61420e84612c58565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104ba5761428a8693614298926142c4965f926143325750612d5e565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104ba575f93614313575b50501061430157565b604051633684c65960e01b8152600490fd5b61432a929350803d106104b3576104a4818361144b565b905f806142f8565b610835919250863d88116104b3576104a4818361144b565b5050565b604051600160f81b60208201525f60218201523060601b602c820152602081526108e6816113fd565b5f19811461196e5760010190565b356108e68161260e565b92939190918051936143a184866126a7565b6143aa87612699565b036143ec576143b886613839565b945f8094885f965f5b8281106144245750501591506143fe905057505050036143ec576143e8915f1901906129d8565b5190565b604051631a8a024960e11b8152600490fd5b9195509293501590506144165750506143e8906129cb565b61442092506138b3565b3590565b8a868610156144d757506144566144518261444861444189614377565b988c6129d8565b51955b876138bc565b614385565b156144bc578a8686101561449b57506144876001929361447f61447888614377565b978b6129d8565b515b9061460b565b614491828d6129d8565b5201908a916143c1565b92614487906144b6846144b060019691614377565b966129d8565b51614481565b61448760019293613af46144cf8c614377565b9b8d8b6138bc565b91614451826144ed836144b06144569591614377565b519561444b565b609a548061450157505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031661173f565b6001600160601b039081811161454a571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b156145ea575f805160206146db83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156145cf5761241a9161462c565b5050346145d857565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b8181101561461f575f5260205260405f2090565b905f5260205260405f2090565b5f806108e693602081519101845af461464361293e565b91614669565b614651613f24565b61465757565b6040516389a1dc6360e01b8152600490fd5b9061467e57508051156136f957805190602001fd5b815115806146b1575b61468f575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561468756fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220575227d2ab6f6dc09c808397834f8b2864f1374a42b4bf85b19f335a03976c6764736f6c63430008160033", + "deployedBytecode": "0x60806040526004361015610022575b3615610018575f80fd5b610020612c4e565b005b5f3560e01c806301e1d114146102e1578063066055e0146102dc57806307a2d13a146102d757806318f72950146102d25780631a7ff553146102cd578063201b9eb5146102c85780632999ad3f146102c35780632cdf7401146102be5780633229fa95146102b957806333194c0a146102b45780633a98ef39146102af578063439fab91146102aa57806343e82a79146102a557806346904840146102a05780634ec96b221461029b5780634f1ef28614610296578063514e27081461029157806352d1902d1461028c57806353156f281461028757806354fd4d50146102825780635c60da1b1461027d5780635cfc1a51146102785780635dddf3a81461027357806360d60e6e1461026e57806372b410a81461026957806376b58b90146102645780637bde82f21461025f5780637fd6f15c1461025a5780638697d2c2146102555780638ceab9aa146102505780639b401cde1461024b578063a1bf49aa14610246578063a49a1e7d14610241578063aaa4e8361461023c578063ac9650d814610237578063ad3cb1cc14610232578063c6e6f5921461022d578063d83ad00c14610228578063e74b981b14610223578063ef2a21581461021e578063f04da65b14610219578063f5e9de4d14610214578063f851a4401461020f5763f9609f080361000e5761230d565b6122e6565b612156565b61211b565b612093565b612058565b612032565b612014565b611fcf565b611eda565b611d94565b611d3d565b611d20565b611d03565b611bbd565b611b98565b611b74565b611a51565b611a00565b611973565b6118ce565b6118b4565b61189a565b611866565b61184b565b611827565b6117be565b611752565b6114cc565b611373565b61134b565b610f0c565b610df3565b610d84565b610d4a565b610d1e565b610d04565b6108e9565b610590565b61055d565b610504565b6104bf565b610314565b6102f4565b5f9103126102f057565b5f80fd5b346102f0575f3660031901126102f057602060985460801c604051908152f35b346102f05760203660031901126102f0576001600160801b03600435818116908181036102f057604051633b9e9f0160e21b81523360048201526001600160801b0382166024820152916020836044815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19283156104ba575f93610489575b50335f908152610137602052604090206103b890612351565b936103ca85516001600160801b031690565b1615610477578361040c6103ff6103ef610425946103ea61047399612c58565b612d08565b83516001600160801b031661238a565b6001600160801b03168252565b335f908152610137602052604090206123a3565b6123a3565b604080518381526001600160801b0392909216602083015233917f3f7354ba02880b4fa37a629985852a38417ff369369ce1e52fa6f8342a9100a79190a26040519081529081906020820190565b0390f35b60405163673f032f60e11b8152600490fd5b6104ac91935060203d6020116104b3575b6104a4818361144b565b810190612337565b915f61039f565b503d61049a565b612346565b346102f05760203660031901126102f05760206104dd6004356123d5565b604051908152f35b6001600160a01b038116036102f057565b908160809103126102f05790565b60603660031901126102f05760043561051c816104e5565b602435610528816104e5565b604435906001600160401b0382116102f0576020926105566105516104dd9436906004016104f6565b6123fb565b3490613cdf565b346102f05760203660031901126102f0576004356001600160401b0381116102f0576105516100209136906004016104f6565b346102f05760603660031901126102f05760048035906105af826104e5565b60243590604435926105c0846104e5565b6105c86132d2565b6105d06132f3565b604080516329460cc560e11b81526001600160a01b038381168286019081526020818101889052929693959192907f00000000000000000000000000000000000000000000000000000000000000008416908290899081908a0103815f855af19788156104ba575f9861089e575b50335f90815261013760205260409020839061065990612351565b946001600160801b0361067387516001600160801b031690565b161561083c5761068286612c58565b6106ae6106a161069189612d08565b88516001600160801b031661242c565b6001600160801b03168752565b335f908152609c6020526040902084906106c9905b546123d5565b918a5193848092631331885160e31b82527f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104ba5761075892859261071c925f9261081d575b50612d5e565b9261072e87516001600160801b031690565b908a5180809581946303d1689d60e11b83528a83019190916001600160801b036020820193169052565b03915afa9283156104ba575f936107fe575b5050106107f05750947fa16d97739893e1436c9753925fb5cef174c4f368699dc86cc8fdb0e6e60f8e58916107b7610473976104203360018060a01b03165f5261013760205260405f2090565b84516001600160a01b039485168152602081018790526040810191909152921660608301523391608090a2519081529081906020820190565b8451633684c65960e01b8152fd5b610815929350803d106104b3576104a4818361144b565b905f8061076a565b610835919250843d86116104b3576104a4818361144b565b905f610716565b885163752a536d60e01b8152915083828681865afa80156104ba5761086d61087c9187945f91610881575b50612d08565b6001600160801b031687860152565b610682565b6108989150873d89116104b3576104a4818361144b565b5f610867565b6108b6919850823d84116104b3576104a4818361144b565b965f61063e565b60609060031901126102f057600435906024356108d9816104e5565b906044356108e6816104e5565b90565b346102f0576108f7366108bd565b906001600160a01b0380831615610cf2576109106132f3565b807f00000000000000000000000000000000000000000000000000000000000000001691823b156102f05760408051631d8557d760e01b815260049491905f81878183875af180156104ba57610cd9575b506001600160a01b0383165f9081526101376020526040902061098390612351565b6001600160801b0361099c82516001600160801b031690565b1615610cc9576109ab81612c58565b81516330fe427560e21b81529260a08488817f00000000000000000000000000000000000000000000000000000000000000008a165afa9687156104ba57610a1a975f955f91610c90575b5084516303d1689d60e11b918282528c828060209d8e938883019190602083019252565b0381885afa80156104ba57610a35925f91610c735750612d5e565b95610a536106c38960018060a01b03165f52609c60205260405f2090565b918288118015610c63575b610c5357908a610a9b92610a7988516001600160801b031690565b908951948592839283528883019190916001600160801b036020820193169052565b0381885afa9081156104ba57670de0b6b3a764000093610ad7938d5f94610c2a575b5050610acb610ad191612ab4565b92612ad1565b91612dd8565b1015610c1c578351633b9e9f0160e21b815233918101918252602082018b905294939291889186919082905f90829060400103925af19081156104ba577f61fd285f9e34a3dbfa9846bdcf22a023e37a3c93549902843b30dd74a18c535097610bf995610b7193610bfe575b5050610b546103ff6103ef8c612d08565b6001600160a01b0386165f908152610137602052604090206123a3565b610b7a82613748565b90610bb8610b9d610b8a85612d08565b60985460801c036001600160801b031690565b6001600160801b036098549181199060801b16911617609855565b610bc28286613f93565b610bcc838961369b565b51948594169733978590949392606092608083019660018060a01b03168352602083015260408201520152565b0390a3005b81610c1492903d106104b3576104a4818361144b565b505f80610b43565b835163185cfc6d60e11b8152fd5b610ad1929450610acb9181610c4a92903d106104b3576104a4818361144b565b9391508d610abd565b865163efda1a2760e01b81528490fd5b50610c6c612447565b8811610a5e565b610c8a91508c8d3d106104b3576104a4818361144b565b5f610716565b9050610cb591955060a03d60a011610cc2575b610cad818361144b565b81019061337e565b509692509050945f6109f6565b503d610ca3565b815163673f032f60e11b81528690fd5b80610ce6610cec9261141d565b806102e6565b5f610961565b60405163d92e233d60e01b8152600490fd5b346102f0575f3660031901126102f05760206104dd612447565b346102f0575f3660031901126102f0576020610d38612476565b6040516001600160a01b039091168152f35b346102f0575f3660031901126102f05760206040517fd92dbcef7ed61a67c0eefa7cafcc41f41d9402a5046486977364b4724c821f8b8152f35b346102f0575f3660031901126102f05760206001600160801b0360985416604051908152f35b9060206003198301126102f0576004356001600160401b03928382116102f057806023830112156102f05781600401359384116102f057602484830101116102f0576024019190565b610dfc36610daa565b905f805160206146fb83398151915254916001600160401b0360ff8460401c1615931680159081610f04575b6001149081610efa575b159081610ef1575b50610edf575f805160206146fb833981519152805467ffffffffffffffff19166001179055610e6d9183610ebb576124c6565b610e7357005b5f805160206146fb833981519152805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b5f805160206146fb833981519152805460ff60401b1916600160401b1790556124c6565b60405163f92ee8a960e01b8152600490fd5b9050155f610e3a565b303b159150610e32565b849150610e28565b346102f057610f1a366108bd565b906001600160a01b039081831615610cf257610f346132f3565b817f000000000000000000000000000000000000000000000000000000000000000016803b156102f05760408051631d8557d760e01b815260049291905f81858183875af180156104ba57611338575b506001600160a01b0384165f90815261013760205260409020610fa690612351565b926001600160801b03610fc085516001600160801b031690565b161561132a57610fcf84612c58565b81516330fe427560e21b81529360a08583817f00000000000000000000000000000000000000000000000000000000000000008b165afa9384156104ba575f955f956112fc575b5083516303d1689d60e11b8082528482018c81529197602094939285908a90819083015b0381865afa9889156104ba575f996112dd575b506001600160a01b038a165f908152609c6020526040902061106e906106c3565b90818a1180156112cd575b6112bd576110b4908661109387516001600160801b031690565b8a51809481928883528c83019190916001600160801b036020820193169052565b0381885afa9182156104ba575f9261129c575b506110d29192612d5e565b1161128c578551633b9e9f0160e21b815233868201908152602081018e905290919085908390819060400103815f875af19182156104ba57859261126f575b5061111b8d612d08565b84516001600160801b0316906111309161238a565b6001600160801b031684526001600160a01b038a165f908152610137602052604090208461115d916123a3565b61116689613748565b976111708a612d08565b60985460801c036001600160801b031661119f906001600160801b036098549181199060801b16911617609855565b6111a9898c613f93565b6001600160a01b038b165f908152609c60205260409020546111ca906123d5565b906111d491612d5e565b935187519182526001600160801b0316868201908152909283918290036020019082905afa9283156104ba575f93611250575b505011611242575091610bf9917f57f5eb636bf62215c111b54545422f11dfb0cb115f606be905f0be08e8859dd3959493610bcc838961369b565b9051631d8fa13d60e31b8152fd5b611267929350803d106104b3576104a4818361144b565b905f80611207565b61128590833d85116104b3576104a4818361144b565b505f611111565b855163324b20e160e11b81528590fd5b6110d292506112b790883d8a116104b3576104a4818361144b565b916110c7565b875163efda1a2760e01b81528790fd5b506112d6612447565b8a11611079565b6112f5919950853d87116104b3576104a4818361144b565b975f61104d565b61103a92965061131c91955060a03d60a011610cc257610cad818361144b565b505050959095949091611016565b905163673f032f60e11b8152fd5b80610ce66113459261141d565b5f610f84565b346102f0575f3660031901126102f0576065546040516001600160a01b039091168152602090f35b346102f05760203660031901126102f057600435611390816104e5565b60018060a01b03165f52610137602052602060405f20604051906113b3826113fd565b54906001600160801b03918281169081835260801c848301526113db575b5116604051908152f35b6113e481612c58565b6113d1565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761141857604052565b6113e9565b6001600160401b03811161141857604052565b606081019081106001600160401b0382111761141857604052565b90601f801991011681019081106001600160401b0382111761141857604052565b60405190611479826113fd565b565b6001600160401b03811161141857601f01601f191660200190565b9291926114a28261147b565b916114b0604051938461144b565b8294818452818301116102f0578281602093845f960137010152565b6040806003193601126102f05760049081356114e7816104e5565b6024356001600160401b0381116102f057366023820112156102f0576115169036906024818701359101611496565b9161151f613482565b8051926115568461154860209363439fab9160e01b858401528460248401526044830190611e52565b03601f19810186528561144b565b61155e613482565b611566613735565b6001600160a01b0383811680159291908790841561171d575b84156116af575b841561164b575b505082156115b5575b50506115a657610020838361410a565b516355299b4960e01b81528390fd5b83516345da87c560e01b81526001600160a01b03861688820190815292935091839183918290819060200103917f0000000000000000000000000000000000000000000000000000000000000000165afa9182156104ba575f9261161e575b5050155f80611596565b61163d9250803d10611644575b611635818361144b565b810190612618565b5f80611614565b503d61162b565b855163054fd4d560e41b81529294508391839182905afa9081156104ba5760029160ff915f91611682575b5016141591865f61158d565b6116a29150843d86116116a8575b61169a818361144b565b8101906140f1565b5f611676565b503d611690565b935050835163198ca60560e11b815282818981875afa9081156104ba5788917fd92dbcef7ed61a67c0eefa7cafcc41f41d9402a5046486977364b4724c821f8b915f91611700575b50141593611586565b6117179150853d87116104b3576104a4818361144b565b5f6116f7565b5f805160206146db83398151915254909450849061174b906001600160a01b03165b6001600160a01b031690565b149361157f565b346102f05760203660031901126102f0576004356001600160a01b036117766125ef565b1633036117ac578060d0555f60d155337fbe9758e2d6800505eeb0292a08fe647c52762ccea131177456e7062dd77b41065f80a3005b604051634ca8886760e01b8152600490fd5b346102f0575f3660031901126102f0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036118155760206040515f805160206146db8339815191528152f35b60405163703e46dd60e11b8152600490fd5b5f3660031901126102f0576001600160a01b03611842612476565b1633036117ac57005b346102f0575f3660031901126102f057602060405160018152f35b346102f0575f3660031901126102f0575f805160206146db833981519152546040516001600160a01b039091168152602090f35b346102f0575f3660031901126102f05760206104dd6125e1565b346102f0575f3660031901126102f0576020610d386125ef565b346102f05760203660031901126102f057609a80549081905f6004355b84821061191c5750505081101561191157610473905b6040519081529081906020820190565b506104735f19611901565b909193808316906001818518811c830180931161196e575f8790525f805160206146bb8339815191528301546001600160a01b0316841015611963575050935b91906118eb565b90959101925061195c565b612376565b346102f0575f3660031901126102f057604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104ba576020915f916119e3575b506040519015158152f35b6119fa9150823d841161164457611635818361144b565b5f6119d8565b346102f05760803660031901126102f057610473611a34600435611a23816104e5565b60643590604435906024359061263a565b604080519384526020840192909252908201529081906060820190565b346102f0576040806003193601126102f05760043560243591611a73836104e5565b611a7b614649565b8115611b64576001600160a01b0383168015611b5357611a9a836123d5565b928315611b4257611aa9612447565b8411611b3157611ae08461047396611ad1610b9d611ac684612d08565b60985460801c61238a565b611adb8433613f93565b61369b565b8251848152602081019190915233907f5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea834809080604081015b0390a3611b23336141b5565b519081529081906020820190565b82516396d8043360e01b8152600490fd5b82516318374fd160e21b8152600490fd5b815163d92e233d60e01b8152600490fd5b51636edcc52360e01b8152600490fd5b346102f0575f3660031901126102f057602061ffff60655460a01c16604051908152f35b346102f05760603660031901126102f057610473611a346044356024356004356126b4565b346102f0576040806003193601126102f0576004359060243590611be0826104e5565b611be86132d2565b8215611b64576001600160a01b0382168015611b535783611cc8611cac61047396611c2a611c1e6099546001600160801b031690565b6001600160801b031690565b81611c8a611c3f83611c3a6144f4565b6126a7565b89516001600160a01b03909b1660208c019081524260408d015260608c01829052909a611c7981608081015b03601f19810183528261144b565b5190205f52609b60205260405f2090565b55335f908152609c60205260409020611ca483825461262d565b905501612d08565b6001600160801b03166001600160801b03196099541617609955565b8251848152602081019190915233907f211091c5bf013c1230f996c3bb2bc327e3de429a3d3c356dcea9a0c858bc407f908060408101611b17565b346102f0575f3660031901126102f057602060d054604051908152f35b346102f0575f3660031901126102f057602060d154604051908152f35b346102f057611d8f7f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf611d6f36610daa565b9290611d79613735565b604051918291602083523395602084019161284b565b0390a2005b346102f05760203660031901126102f057600435611db1816104e5565b611db9613735565b6001600160a01b03168015610cf25760d280546001600160a01b03191682179055337fb710e1d0ebf395f895942ac4e559a4a86d57f748a90cf05e9d70798c67e9c65b5f80a3005b9181601f840112156102f0578235916001600160401b0383116102f0576020808501948460051b0101116102f057565b5f5b838110611e425750505f910152565b8181015183820152602001611e33565b90602091611e6b81518092818552858086019101611e31565b601f01601f1916010190565b6020808201906020835283518092526040830192602060408460051b8301019501935f915b848310611eac5750505050505090565b9091929394958480611eca600193603f198682030187528a51611e52565b9801930193019194939290611e9c565b346102f05760203660031901126102f057600480356001600160401b0381116102f057611f0b903690600401611e01565b91611f1583612882565b925f5b818110611f2d57604051806104738782611e77565b5f80611f3a838588612911565b60409391611f4c855180938193612931565b0390305af490611f5a61293e565b9115611f81575090600191611f6f82886129d8565b52611f7a81876129d8565b5001611f18565b848260448151106102f057611fa58183611fba93015160248091830101910161296d565b925162461bcd60e51b81529283928301611fbe565b0390fd5b9060206108e6928181520190611e52565b346102f0575f3660031901126102f057610473604051611fee816113fd565b60058152640352e302e360dc1b6020820152604051918291602083526020830190611e52565b346102f05760203660031901126102f05760206104dd600435613748565b346102f0575f3660031901126102f05760206001600160801b0360995416604051908152f35b346102f05760203660031901126102f057610020600435612078816104e5565b612080613735565b6137d7565b908160a09103126102f05790565b346102f05760803660031901126102f0576001600160401b036004358181116102f0576120c4903690600401612085565b6024358281116102f0576120dc903690600401611e01565b6044929192358481116102f0576120f7903690600401611e01565b916064359586116102f057612113610020963690600401611e01565b959094612ae8565b346102f05760203660031901126102f057600435612138816104e5565b60018060a01b03165f52609c602052602060405f2054604051908152f35b346102f0576040806003193601126102f0576004906001600160401b0382358181116102f0576121899036908501612085565b906024359081116102f0576121a19036908501611e01565b9390926121ac6132f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156102f0575f8251809263837d444160e01b82528183816121fb8a8a8301612a1d565b03925af180156104ba576122d3575b506801bc16d674ec80000061221d612447565b106122c6578083019360b061223286866128df565b9050036122b8576122846122889160d1549760d0549061227761226f8b6122598c8c6128df565b611c6b8b94929451938492602084019687612c1a565b519020612c37565b6020815191012092613acc565b1590565b6122ab576100206001866122a561229f88886128df565b90613b04565b0160d155565b516309bde33960e01b8152fd5b5051631a0a9b9f60e21b8152fd5b516396d8043360e01b8152fd5b80610ce66122e09261141d565b5f61220a565b346102f0575f3660031901126102f0575f546040516001600160a01b039091168152602090f35b60403660031901126102f05760206104dd60043561232a816104e5565b60243590610556826104e5565b908160209103126102f0575190565b6040513d5f823e3d90fd5b9060405161235e816113fd565b91546001600160801b038116835260801c6020830152565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b03918216908216039190821161196e57565b815160209092015160801b6fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6098546001600160801b03811690816123ed57505090565b916108e69260801c90612dd8565b61240490612f40565b908061241d575b5061241257565b61241a6131d5565b50565b612426906130d6565b5f61240b565b9190916001600160801b038080941691160191821161196e57565b4760995461245d6001600160801b0382166123d5565b9060801c01908181115f14612470570390565b50505f90565b61016a546001600160a01b0316801561248c5790565b507f000000000000000000000000000000000000000000000000000000000000000090565b908160209103126102f057516108e6816104e5565b60405163e7f6f22560e01b8152602092908381600481335afa9081156104ba575f916125c4575b50604051636f4fa30f60e01b8152918483600481335afa9283156104ba575f93612595575b5083019380848603126102f05783356001600160401b03948582116102f05701936060858703126102f0576040519461254a86611430565b803586528281013561ffff811681036102f0578387015260408101359182116102f057019480601f870112156102f0578561258b9261147997359101611496565b60408401526133a5565b6125b6919350853d87116125bd575b6125ae818361144b565b8101906124b1565b915f612512565b503d6125a4565b6125db9150843d86116125bd576125ae818361144b565b5f6124ed565b609d54806108e657505f1990565b60d2546001600160a01b039081168061260957505f541690565b905090565b801515036102f057565b908160209103126102f057516108e68161260e565b9190820391821161196e57565b604080516001600160a01b03909216602083019081529082019390935260608101829052909261268a9290916126738160808101611c6b565b5190205f52609b60205260405f2054928391613500565b909182810390811161196e5792565b906001820180921161196e57565b9190820180921161196e57565b929190915f936126e47f0000000000000000000000000000000000000000000000000000000000000000856126a7565b42106128215760408051336020820190815291810186905260608082018490528152601f19916127259161271960808261144b565b5190209486843361263a565b90969095878781156128135750505f908152609b6020526040812055600182116127c9575b50505061278261276761275c85612d08565b60995460801c61238a565b6001600160801b036099549181199060801b16911617609955565b61278c833361369b565b6040805191825260208201869052810183905233907feb3b05c070c24f667611fdb3ff75fe007d42401c573aed8d8faca95fd00ccb5690606090a2565b61280a919297506127da87856126a7565b60408051336020820190815291810193909352606083018290526080998a0183529098909190611c79908261144b565b555f808061274a565b959950975093955050505050565b604051631613b7eb60e01b8152600490fd5b90603060609281835260208301375f60508201520190565b908060209392818452848401375f828201840152601f01601f1916010190565b6001600160401b0381116114185760051b60200190565b9061288c8261286b565b612899604051918261144b565b82815280926128aa601f199161286b565b01905f5b8281106128ba57505050565b8060606020809385010152016128ae565b634e487b7160e01b5f52603260045260245ffd5b903590601e19813603018212156102f057018035906001600160401b0382116102f0576020019181360383136102f057565b9082101561292c576129289160051b8101906128df565b9091565b6128cb565b908092918237015f815290565b3d15612968573d9061294f8261147b565b9161295d604051938461144b565b82523d5f602084013e565b606090565b6020818303126102f0578051906001600160401b0382116102f0570181601f820112156102f057805161299f8161147b565b926129ad604051948561144b565b818452602082840101116102f0576108e69160208085019101611e31565b80511561292c5760200190565b805182101561292c5760209160051b010190565b9035601e19823603018112156102f05701602081359101916001600160401b0382116102f05781360383136102f057565b9060a06108e692602081528235602082015260208301356040820152612a59612a4960408501856129ec565b84606085015260c084019161284b565b90612a8c612a81612a6d60608701876129ec565b601f1985870381016080870152959161284b565b9460808101906129ec565b9390928286030191015261284b565b906801bc16d674ec800000918083029283040361196e57565b90670de0b6b3a76400009182810292818404149015171561196e57565b906127109182810292818404149015171561196e57565b929094939195612af66132f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031695863b156102f0576040965f8851809263837d444160e01b8252818381612b4a8c60048301612a1d565b03925af180156104ba57612c07575b50612b62612447565b612b6b89612a9b565b11612bf65787158015612bdc575b612bcb5791612ba9959391612ba3896122849795612b9d60d054978c8101906128df565b90613947565b94613aba565b612bbb57506114799060d1540160d155565b516309bde33960e01b8152600490fd5b8651631c6c4cf360e31b8152600490fd5b50612be9878601866128df565b905060b089021415612b79565b86516396d8043360e01b8152600490fd5b80610ce6612c149261141d565b5f612b59565b939291602091612c329160408752604087019161284b565b930152565b9060405191602083015260208252611479826113fd565b61241a3433613c17565b60405163752a536d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f91612ce9575b5060208201916001600160801b03918284511691828214612ce25783612cd56103ea612cdd958584865116612dd8565b169052612d08565b169052565b5050505050565b612d02915060203d6020116104b3576104a4818361144b565b5f612ca5565b6001600160801b0390818111612d1c571690565b604490604051906306dfcc6560e41b8252608060048301526024820152fd5b634e487b7160e01b5f52601260045260245ffd5b8115612d59570490565b612d3b565b90808202905f1981840990828083109203918083039214612dcd576127109082821115612dbb577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e91940990828211900360fc1b910360041c170290565b60405163227bc15360e01b8152600490fd5b505061271091500490565b9091828202915f1984820993838086109503948086039514612e4b5784831115612dbb57829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b5050906108e69250612d4f565b908160609103126102f057805191604060208301519201516108e68161260e565b81835290916001600160fb1b0383116102f05760209260051b809284830137010190565b90602082528035602083015260208101358060130b8091036102f05760408301526040810135612ecc816104e5565b6001600160a01b031660608381019190915281013536829003601e19018112156102f05701602081359101906001600160401b0381116102f0578060051b360382136102f05760a0836080806108e69601520191612e79565b9190915f838201938412911290801582169115161761196e57565b6040516325f56f1160e01b81526001600160a01b03929160609082908190612f6b9060048301612e9d565b03815f877f0000000000000000000000000000000000000000000000000000000000000000165af19283156104ba575f915f905f95613091575b50841561303e5781612fb5612476565b16917f000000000000000000000000000000000000000000000000000000000000000016821461303757509060205f92600460405180958193634641257d60e01b83525af19081156104ba57613012925f92613016575b50612f25565b9190565b61303091925060203d6020116104b3576104a4818361144b565b905f61300c565b9081613044575b50509190565b803b156102f057604051636ee3193160e11b815260048101929092525f908290602490829084905af180156104ba5761307e575b8061303e565b80610ce661308b9261141d565b5f613078565b919450506130b7915060603d6060116130bf575b6130af818361144b565b810190612e58565b93905f612fa5565b503d6130a5565b600160ff1b811461196e575f0390565b6130e5611c1e60985460801c90565b5f82126131bc57816130f6916126a7565b90613103610b9d83612d08565b6131186065549161ffff8360a01c1690612d5e565b80156131b757807f555ee6b2ef9506d870f386c067e47d3689435330b012ad263d8cc3531868654793613156611c1e6098546001600160801b031690565b806131a157505061319c90925b6001600160a01b0316916131778484613d8b565b60405193849384604091949392606082019560018060a01b0316825260208201520152565b0390a1565b61319c926131b192039084612dd8565b92613163565b505050565b6103ea610b9d916131cf611479946130c6565b9061262d565b609954906001600160801b0382169182156132cc5760801c6132096131fa824761262d565b613203856123d5565b90613dd7565b9081156132c55761321982613748565b9384156132bd57826132456127676103ea61147996610b9d96611c3a611cac6103ea8d611ac69a61262d565b61324f8187613e3d565b60408051878152602081018390527f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f9190a16103ea6132a161329088612d08565b6098546001600160801b031661238a565b6001600160801b03166001600160801b03196098541617609855565b505f93505050565b505f925050565b505f9150565b6132da613f24565b156132e157565b604051630a62fbdb60e11b8152600490fd5b604051633eb1acf760e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f9161335f575b5061334d57565b60405163e775715160e01b8152600490fd5b613378915060203d60201161164457611635818361144b565b5f613346565b908160a09103126102f0578051916020820151916040810151916080606083015192015190565b6133ad613fe0565b60408301516133ba613fe0565b5f80546001600160a01b0319166001600160a01b03841617905560405133917f2013570c343af8ab14a9778150e381a0fda34ed6368127a95fd5e7210cbec5bf919081906134089082611fbe565b0390a2602083015192613419613fe0565b61271061ffff851611613470576134689361343661345b936137d7565b6065805461ffff60a01b191660a09290921b61ffff60a01b169190911790555161400e565b61346361403e565b61405f565b61147961408e565b604051638a81d3b360e01b8152600490fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163081149182156134c0575b505061181557565b5f805160206146db8339815191525416141590505f806134b8565b906040516134e8816113fd565b91546001600160a01b038116835260a01c6020830152565b609a545f948594939091808410801590613693575b6136865783613650575f5b609a5f526001600160a01b03166135455f805160206146bb83398151915286016134db565b805190979061355c906001600160a01b031661173f565b986135816135756020809b01516001600160601b031690565b6001600160601b031690565b948381108015613646575b6136345791600193979a956135ab6135b7939488035b838c0390613dd7565b80920198870391612dd8565b0197019380861180159061362a575b61361f57609a5f5282906135e85f805160206146bb83398151915287016134db565b805190890151969992966001600160a01b0390911694600193926135b79290916001600160601b03909116906135ab9088036135a2565b945050509250509190565b50818510156135c6565b60405163e8722f8f60e01b8152600490fd5b50808b111561358c565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be38401546001600160a01b0316613520565b505093505050505f905f90565b508415613515565b907f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00916002835414613723576002835581471061370b575f918291829182916001600160a01b03165af16136ed61293e565b50156136f95760019055565b604051630a12f52160e11b8152600490fd5b60405163cd78605960e01b8152306004820152602490fd5b604051633ee5aeb560e01b8152600490fd5b5f546001600160a01b031633036117ac57565b609854906001600160801b03821681158015613777575b1561376a5750905090565b6108e69260801c91612dd8565b50801561375f565b6098546001600160801b03811690821580156137cf575b156137a057505090565b60801c906137af828285612dd8565b928215612d5957096137be5790565b60018101809111156108e657612376565b508115613796565b6137df6132f3565b6001600160a01b0316801561382757606580546001600160a01b03191682179055337faaebcf1bfa00580e41d966056b48521fa9f202645c86d4ddf28113e617c1b1d35f80a3565b604051630ed1b8b360e31b8152600490fd5b906138438261286b565b613850604051918261144b565b8281528092613861601f199161286b565b0190602036910137565b906030116102f05790603090565b906090116102f05760300190606090565b9060b0116102f05760900190602090565b909392938483116102f05784116102f0578101920390565b901561292c5790565b919081101561292c5760051b0190565b3590602081106138da575090565b5f199060200360031b1b1690565b96959490612c3293613909613917926060979560808c5260808c019161284b565b9089820360208b0152611e52565b91878303604089015261284b565b9060206108e6928181520190612833565b9160206108e693818152019161284b565b9193929060d154925f925f9061395c81613839565b9761396561434e565b935f9760018060a01b037f000000000000000000000000000000000000000000000000000000000000000016945b848a106139a65750505050505050505050565b60b06139b691018099898561389b565b9960409a8d6139f28d516139da6020918281019061226f81611c6b8c8a8d87612c1a565b8051910120916139eb858b8b6138bc565b35906129d8565b526139fd818461386b565b9093613a1d613a17613a0f8584613879565b95909361388a565b906138cc565b908a3b156102f0578b8f5f93613a48915196879485946304512a2360e31b8652888c600488016138e8565b03816801bc16d674ec8000008d5af19384156104ba57613a9b60018e7f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb1958298613aa7575b5097019e5192839283613936565b0390a101989097613993565b80610ce6613ab49261141d565b5f613a8d565b90613ac8949593929161438f565b1490565b9192915f915b808310613ae0575050501490565b909192613afb600191613af48685876138bc565b359061460b565b93019190613ad2565b816030116102f057613a17917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316613b4261434e565b90613b59613b508486613879565b9690948661388a565b94813b156102f0576801bc16d674ec8000005f94613bbf97604051988996879586946304512a2360e31b865260806004870152613bb0613b9d8d6084890190612833565b60031994858983030160248a0152611e52565b9286840301604487015261284b565b90606483015203925af19081156104ba577f64b6e61d93b7a91e8cc4376183ede0997a27b44fd9dd2f30a866b2a5730efdb19261319c92613c08575b5060405191829182613925565b613c119061141d565b5f613bfb565b9190613c216132f3565b6001600160a01b038316908115610cf2578015613ccd5780613c48611c1e60985460801c90565b0193613c526125e1565b8511613cbb57610b9d94613c7991613c74613c6c8561377f565b978893612d08565b613d8b565b60408051918252602082018590525f9082015233907f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c9080606081015b0390a3565b6040516304ffa0ff60e51b8152600490fd5b6040516318374fd160e21b8152600490fd5b90929192613ceb6132f3565b6001600160a01b038216918215610cf2578115613ccd5781613d12611c1e60985460801c90565b01613d1b6125e1565b8111613cbb57610b9d95613d62613cb6927f861a4138e41fb21c121a7dbb1053df465c837fc77380cc7226189a662281be2c94613c74613d5a8861377f565b9a8b93612d08565b60408051948552602085018890526001600160a01b039091169084015233929081906060820190565b613d9482612d08565b60985490613dac6001600160801b039182841661242c565b16906001600160801b0319161760985560018060a01b03165f52609c60205260405f20908154019055565b9080821015612609575090565b609a5490600160401b821015611418576001820180609a5582101561292c57609a5f52805160209091015160a01b6001600160a01b0319166001600160a01b0391909116175f805160206146bb83398151915290910155565b9081158015613f1c575b613f0a57609a5480613ed457505f905b6001600160a01b0391821692830192831061196e57818311613eb4576114799291613e9f613e87613eaf93614536565b91613e9061146c565b94166001600160a01b03168452565b6001600160601b03166020830152565b613de4565b6040516306dfcc6560e41b815260a0600482015260248101849052604490fd5b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031690613e57565b604051632ec8835b60e21b8152600490fd5b508015613e47565b604051630156a69560e11b81523060048201526020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156104ba575f91613f7a575090565b6108e6915060203d60201161164457611635818361144b565b60018060a01b03165f52609c60205260405f2090815481810390811161196e57613fbd9255612d08565b609854906001600160801b03908183160316906001600160801b03191617609855565b60ff5f805160206146fb8339815191525460401c1615613ffc57565b604051631afcd79f60e31b8152600490fd5b614016613fe0565b801561402c57600181016140275750565b609d55565b6040516331278a8760e01b8152600490fd5b614046613fe0565b6801bc16d674ec8000006140586125e1565b1061402c57565b614067613fe0565b6001600160a01b0316806140785750565b61016a80546001600160a01b0319169091179055565b614096613fe0565b61409e613fe0565b6140a6613fe0565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055633b9aca0034106140df5761241a3430613c17565b60405163ea2559bb60e01b8152600490fd5b908160209103126102f0575160ff811681036102f05790565b6040516352d1902d60e01b81529290916020846004816001600160a01b0387165afa5f9481614194575b5061415a57604051634c9c8ce360e01b81526001600160a01b0384166004820152602490fd5b90915f805160206146db833981519152840361417b57611479929350614569565b604051632a87526960e21b815260048101859052602490fd5b6141ae91955060203d6020116104b3576104a4818361144b565b935f614134565b6001600160a01b0381165f908152610137602052604090206141d690612351565b906001600160801b036141f083516001600160801b031690565b161561434a576106c3614227916142056132f3565b61420e84612c58565b6001600160a01b03165f908152609c6020526040902090565b604051631331885160e31b8152602092916001600160a01b0384836004817f000000000000000000000000000000000000000000000000000000000000000085165afa9182156104ba5761428a8693614298926142c4965f926143325750612d5e565b94516001600160801b031690565b6040516303d1689d60e11b81526001600160801b03909116600482015292839190829081906024820190565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa9283156104ba575f93614313575b50501061430157565b604051633684c65960e01b8152600490fd5b61432a929350803d106104b3576104a4818361144b565b905f806142f8565b610835919250863d88116104b3576104a4818361144b565b5050565b604051600160f81b60208201525f60218201523060601b602c820152602081526108e6816113fd565b5f19811461196e5760010190565b356108e68161260e565b92939190918051936143a184866126a7565b6143aa87612699565b036143ec576143b886613839565b945f8094885f965f5b8281106144245750501591506143fe905057505050036143ec576143e8915f1901906129d8565b5190565b604051631a8a024960e11b8152600490fd5b9195509293501590506144165750506143e8906129cb565b61442092506138b3565b3590565b8a868610156144d757506144566144518261444861444189614377565b988c6129d8565b51955b876138bc565b614385565b156144bc578a8686101561449b57506144876001929361447f61447888614377565b978b6129d8565b515b9061460b565b614491828d6129d8565b5201908a916143c1565b92614487906144b6846144b060019691614377565b966129d8565b51614481565b61448760019293613af46144cf8c614377565b9b8d8b6138bc565b91614451826144ed836144b06144569591614377565b519561444b565b609a548061450157505f90565b609a5f527f44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be301546001600160a01b031661173f565b6001600160601b039081811161454a571690565b604490604051906306dfcc6560e41b8252606060048301526024820152fd5b90813b156145ea575f805160206146db83398151915280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156145cf5761241a9161462c565b5050346145d857565b60405163b398979f60e01b8152600490fd5b604051634c9c8ce360e01b81526001600160a01b0383166004820152602490fd5b8181101561461f575f5260205260405f2090565b905f5260205260405f2090565b5f806108e693602081519101845af461464361293e565b91614669565b614651613f24565b61465757565b6040516389a1dc6360e01b8152600490fd5b9061467e57508051156136f957805190602001fd5b815115806146b1575b61468f575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561468756fe44da158ba27f9252712a74ff6a55c5d531f69609f1f6e7f17c4443a8e2089be4360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220575227d2ab6f6dc09c808397834f8b2864f1374a42b4bf85b19f335a03976c6764736f6c63430008160033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/shared/constants.ts b/test/shared/constants.ts index c6b2081b..557160b8 100644 --- a/test/shared/constants.ts +++ b/test/shared/constants.ts @@ -34,7 +34,7 @@ export const ORACLES = [ export const REWARDS_MIN_ORACLES = 6 export const VALIDATORS_MIN_ORACLES = 6 export const ORACLES_CONFIG = 'QmbwQ6zFEWs1SjLPGk4NNJqn4wduVe6dK3xyte2iG59Uru' -export const EXITING_ASSETS_MIN_DELAY = ONE_DAY +export const EXITING_ASSETS_MIN_DELAY = 30 * 60 * 60 // 30 hours export const OSTOKEN_FEE = 500 // 5% export const OSTOKEN_CAPACITY = ethers.parseEther('10000000') export const OSTOKEN_NAME = 'Staked ETH' diff --git a/test/shared/contracts.ts b/test/shared/contracts.ts index c5a4a1e2..1718dc1e 100644 --- a/test/shared/contracts.ts +++ b/test/shared/contracts.ts @@ -1,7 +1,32 @@ import { ContractFactory } from 'ethers' import { ethers } from 'hardhat' -import { ethValidatorsRegistry } from '../../helpers/constants' +import EthValidatorsRegistry from './artifacts/EthValidatorsRegistry.json' +import EthVaultV1 from './artifacts/EthVault.json' +import EthErc20VaultV1 from './artifacts/EthErc20Vault.json' +import EthPrivErc20VaultV1 from './artifacts/EthPrivErc20Vault.json' +import EthPrivVaultV1 from './artifacts/EthPrivVault.json' +import EthGenesisVaultV1 from './artifacts/EthGenesisVault.json' export async function getValidatorsRegistryFactory(): Promise { - return await ethers.getContractFactory(ethValidatorsRegistry.abi, ethValidatorsRegistry.bytecode) + return await ethers.getContractFactory(EthValidatorsRegistry.abi, EthValidatorsRegistry.bytecode) +} + +export async function getEthVaultV1Factory(): Promise { + return await ethers.getContractFactory(EthVaultV1.abi, EthVaultV1.bytecode) +} + +export async function getEthErc20VaultV1Factory(): Promise { + return await ethers.getContractFactory(EthErc20VaultV1.abi, EthErc20VaultV1.bytecode) +} + +export async function getEthPrivErc20VaultV1Factory(): Promise { + return await ethers.getContractFactory(EthPrivErc20VaultV1.abi, EthPrivErc20VaultV1.bytecode) +} + +export async function getEthPrivVaultV1Factory(): Promise { + return await ethers.getContractFactory(EthPrivVaultV1.abi, EthPrivVaultV1.bytecode) +} + +export async function getEthGenesisVaultV1Factory(): Promise { + return await ethers.getContractFactory(EthGenesisVaultV1.abi, EthGenesisVaultV1.bytecode) } diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index 223b56d4..d543b21a 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -1,5 +1,5 @@ import hre, { ethers } from 'hardhat' -import { BigNumberish, Contract, parseEther, Signer, Wallet } from 'ethers' +import { BigNumberish, Contract, ContractFactory, parseEther, Signer, Wallet } from 'ethers' import { simulateDeployImpl } from '@openzeppelin/hardhat-upgrades/dist/utils' import { impersonateAccount, @@ -10,8 +10,14 @@ import EthereumWallet from 'ethereumjs-wallet' import { CumulativeMerkleDrop, CumulativeMerkleDrop__factory, + EthBlocklistErc20Vault, + EthBlocklistErc20Vault__factory, + EthBlocklistVault, + EthBlocklistVault__factory, EthErc20Vault, EthErc20Vault__factory, + EthFoxVault, + EthFoxVault__factory, EthGenesisVault, EthGenesisVault__factory, EthPrivErc20Vault, @@ -19,7 +25,6 @@ import { EthPrivVault, EthPrivVault__factory, EthVault, - EthFoxVault, EthVault__factory, EthVaultFactory, EthVaultFactory__factory, @@ -30,10 +35,10 @@ import { Keeper__factory, OsToken, OsToken__factory, - OsTokenVaultController, - OsTokenVaultController__factory, OsTokenConfig, OsTokenConfig__factory, + OsTokenVaultController, + OsTokenVaultController__factory, PoolEscrowMock, PoolEscrowMock__factory, PriceFeed, @@ -46,7 +51,6 @@ import { SharedMevEscrow__factory, VaultsRegistry, VaultsRegistry__factory, - EthFoxVault__factory, } from '../../typechain-types' import { getValidatorsRegistryFactory } from './contracts' import { @@ -68,7 +72,7 @@ import { SECURITY_DEPOSIT, VALIDATORS_MIN_ORACLES, } from './constants' -import { EthErc20VaultInitParamsStruct, EthVaultInitParamsStruct } from './types' +import { EthErc20VaultInitParamsStruct, EthVaultInitParamsStruct, VaultType } from './types' import { DepositorMock } from '../../typechain-types/contracts/mocks/DepositorMock' import { DepositorMock__factory } from '../../typechain-types/factories/contracts/mocks/DepositorMock__factory' import { UnknownVaultMock } from '../../typechain-types/contracts/mocks/UnknownVaultMock' @@ -103,9 +107,20 @@ export const transferOwnership = async function ( await contract.connect(newOwner).acceptOwnership() } +export const upgradeVaultToV2 = async function ( + vault: VaultType, + implementation: string +): Promise { + const adminAddr = await vault.admin() + const admin = await ethers.getImpersonatedSigner(adminAddr) + await setBalance(adminAddr, ethers.parseEther('1')) + await vault.connect(admin).upgradeToAndCall(implementation, '0x') + return vault +} + export const updateVaultState = async function ( keeper: Keeper, - vault: EthVault | EthPrivVault | EthErc20Vault | EthPrivErc20Vault | EthGenesisVault, + vault: VaultType, harvestParams: IKeeperRewards.HarvestParamsStruct ) { if (!(await keeper.canHarvest(await vault.getAddress()))) { @@ -114,9 +129,7 @@ export const updateVaultState = async function ( await vault.updateState(harvestParams) } -export const createDepositorMock = async function ( - vault: EthVault | EthFoxVault -): Promise { +export const createDepositorMock = async function (vault: VaultType): Promise { const depositorMockFactory = await ethers.getContractFactory('DepositorMock') const contract = await depositorMockFactory.deploy(await vault.getAddress()) return DepositorMock__factory.connect( @@ -383,7 +396,7 @@ export const deployGenesisVaultImpl = async function ( keeper: Keeper, vaultsRegistry: VaultsRegistry, validatorsRegistry: Contract, - osToken: OsToken, + osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, poolEscrow: PoolEscrowMock, @@ -394,7 +407,7 @@ export const deployGenesisVaultImpl = async function ( await keeper.getAddress(), await vaultsRegistry.getAddress(), await validatorsRegistry.getAddress(), - await osToken.getAddress(), + await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), await poolEscrow.getAddress(), @@ -433,6 +446,44 @@ export const deployVaultImplementation = async function ( return vaultImpl } +export async function deployEthVaultV1( + implFactory: ContractFactory, + admin: Signer, + keeper: Keeper, + vaultsRegistry: VaultsRegistry, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + osTokenConfig: OsTokenConfig, + sharedMevEscrow: SharedMevEscrow, + encodedParams: string, + isOwnMevEscrow = false +): Promise { + const constructorArgs = [ + await keeper.getAddress(), + await vaultsRegistry.getAddress(), + await validatorsRegistry.getAddress(), + await osTokenVaultController.getAddress(), + await osTokenConfig.getAddress(), + await sharedMevEscrow.getAddress(), + EXITING_ASSETS_MIN_DELAY, + ] + const vaultImpl = await implFactory.deploy(...constructorArgs) + const vaultImplAddr = await vaultImpl.getAddress() + await vaultsRegistry.addVaultImpl(vaultImplAddr) + + const vaultFactory = await createEthVaultFactory(vaultImplAddr, vaultsRegistry) + await vaultsRegistry.addFactory(await vaultFactory.getAddress()) + + const tx = await vaultFactory.connect(admin).createVault(encodedParams, isOwnMevEscrow, { + value: SECURITY_DEPOSIT, + }) + return new Contract( + await extractVaultAddress(tx), + implFactory.interface, + await ethers.provider.getSigner() + ) +} + export const encodeEthVaultInitParams = function (vaultParams: EthVaultInitParamsStruct): string { return ethers.AbiCoder.defaultAbiCoder().encode( ['tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)'], @@ -495,6 +546,8 @@ interface EthVaultFixture { ethPrivVaultFactory: EthVaultFactory ethErc20VaultFactory: EthVaultFactory ethPrivErc20VaultFactory: EthVaultFactory + ethBlocklistVaultFactory: EthVaultFactory + ethBlocklistErc20VaultFactory: EthVaultFactory osToken: OsToken osTokenVaultController: OsTokenVaultController osTokenConfig: OsTokenConfig @@ -509,7 +562,7 @@ interface EthVaultFixture { createEthFoxVault(admin: Signer, vaultParams: EthVaultInitParamsStruct): Promise createEthVaultMock( - admin: Wallet, + admin: Signer, vaultParams: EthVaultInitParamsStruct, isOwnMevEscrow?: boolean ): Promise @@ -520,6 +573,12 @@ interface EthVaultFixture { isOwnMevEscrow?: boolean ): Promise + createEthBlocklistVault( + admin: Signer, + vaultParams: EthVaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + createEthErc20Vault( admin: Signer, vaultParams: EthErc20VaultInitParamsStruct, @@ -533,6 +592,12 @@ interface EthVaultFixture { isOwnMevEscrow?: boolean ): Promise + createEthBlocklistErc20Vault( + admin: Signer, + vaultParams: EthErc20VaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + createEthGenesisVault( admin: Signer, vaultParams: EthVaultInitParamsStruct, @@ -617,6 +682,8 @@ export const ethVaultFixture = async function (): Promise { 'EthPrivVault', 'EthErc20Vault', 'EthPrivErc20Vault', + 'EthBlocklistVault', + 'EthBlocklistErc20Vault', 'EthVaultMock', ]) { const vaultImpl = await deployVaultImplementation( @@ -645,6 +712,8 @@ export const ethVaultFixture = async function (): Promise { const ethPrivVaultFactory = factories['EthPrivVault'] const ethErc20VaultFactory = factories['EthErc20Vault'] const ethPrivErc20VaultFactory = factories['EthPrivErc20Vault'] + const ethBlocklistVaultFactory = factories['EthBlocklistVault'] + const ethBlocklistErc20VaultFactory = factories['EthBlocklistErc20Vault'] const ethVaultMockFactory = factories['EthVaultMock'] return { @@ -657,6 +726,8 @@ export const ethVaultFixture = async function (): Promise { ethErc20VaultFactory, ethPrivErc20VaultFactory, ethVaultMockFactory, + ethBlocklistVaultFactory, + ethBlocklistErc20VaultFactory, osTokenVaultController, osTokenConfig, osToken, @@ -681,6 +752,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethVaultSharedMevEscrow } const vault = EthVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVaultToV2(vault, implementations['EthVault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -733,7 +805,7 @@ export const ethVaultFixture = async function (): Promise { return vault }, createEthVaultMock: async ( - admin: Wallet, + admin: Signer, vaultParams: EthVaultInitParamsStruct, isOwnMevEscrow = false ): Promise => { @@ -765,10 +837,24 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethPrivVaultSharedMevEscrow } const vault = EthPrivVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVaultToV2(vault, implementations['EthPrivVault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault }, + createEthBlocklistVault: async ( + admin: Signer, + vaultParams: EthVaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + const tx = await ethBlocklistVaultFactory + .connect(admin) + .createVault(encodeEthVaultInitParams(vaultParams), isOwnMevEscrow, { + value: SECURITY_DEPOSIT, + }) + const vaultAddress = await extractVaultAddress(tx) + return EthBlocklistVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, createEthErc20Vault: async ( admin: Signer, vaultParams: EthErc20VaultInitParamsStruct, @@ -790,6 +876,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethErc20VaultSharedMevEscrow } const vault = EthErc20Vault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVaultToV2(vault, implementations['EthErc20Vault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -817,9 +904,26 @@ export const ethVaultFixture = async function (): Promise { vaultAddress, await ethers.provider.getSigner() ) + await upgradeVaultToV2(vault, implementations['EthPrivErc20Vault']) await setBalance(await vault.admin(), parseEther('1000')) return vault }, + createEthBlocklistErc20Vault: async ( + admin: Wallet, + vaultParams: EthErc20VaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + const tx = await ethBlocklistErc20VaultFactory + .connect(admin) + .createVault(encodeEthErc20VaultInitParams(vaultParams), isOwnMevEscrow, { + value: SECURITY_DEPOSIT, + }) + const vaultAddress = await extractVaultAddress(tx) + return EthBlocklistErc20Vault__factory.connect( + vaultAddress, + await ethers.provider.getSigner() + ) + }, createEthGenesisVault: async ( admin: Signer, vaultParams: EthVaultInitParamsStruct, @@ -846,7 +950,7 @@ export const ethVaultFixture = async function (): Promise { keeper, vaultsRegistry, validatorsRegistry, - osToken, + osTokenVaultController, osTokenConfig, sharedMevEscrow, poolEscrow, @@ -879,6 +983,7 @@ export const ethVaultFixture = async function (): Promise { mainnetDeployment.EthGenesisVault, await ethers.provider.getSigner() ) + await upgradeVaultToV2(vault, vaultImpl) await updateVaultState( keeper, vault, diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index f1b5ae95..0d35ddbe 100644 --- a/test/shared/rewards.ts +++ b/test/shared/rewards.ts @@ -1,7 +1,7 @@ import { ethers, network } from 'hardhat' import { Contract, Signer } from 'ethers' import { StandardMerkleTree } from '@openzeppelin/merkle-tree' -import { EthVault, IKeeperRewards, Keeper, EthFoxVault } from '../../typechain-types' +import { EthVault, IKeeperRewards, Keeper } from '../../typechain-types' import { EIP712Domain, EXITING_ASSETS_MIN_DELAY, @@ -22,6 +22,7 @@ import { } from './utils' import { getOraclesSignatures } from './fixtures' import { MAINNET_FORK } from '../../helpers/constants' +import { VaultType } from './types' export type RewardsTree = StandardMerkleTree<[string, bigint, bigint]> @@ -132,8 +133,8 @@ export function getRewardsRootProof(tree: RewardsTree, vaultReward: VaultReward) return tree.getProof([vaultReward.vault, vaultReward.reward, vaultReward.unlockedMevReward]) } -export async function collateralizeEthVault( - vault: EthVault | EthFoxVault, +export async function collateralizeEthV1Vault( + vault: Contract, keeper: Keeper, validatorsRegistry: Contract, admin: Signer @@ -178,6 +179,37 @@ export async function collateralizeEthVault( await setBalance(vaultAddress, balanceBefore) } +export async function collateralizeEthVault( + vault: VaultType, + keeper: Keeper, + validatorsRegistry: Contract, + admin: Signer +) { + const vaultAddress = await vault.getAddress() + const balanceBefore = await ethers.provider.getBalance(vaultAddress) + const adminAddr = await admin.getAddress() + + // register validator + const validatorDeposit = ethers.parseEther('32') + const tx = await vault + .connect(admin) + .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) + const receivedShares = await extractDepositShares(tx) + await registerEthValidator(vault, keeper, validatorsRegistry, admin) + + // exit validator + const response = await vault.connect(admin).enterExitQueue(receivedShares, adminAddr) + const positionTicket = await extractExitPositionTicket(response) + const timestamp = await getBlockTimestamp(response) + + await increaseTime(EXITING_ASSETS_MIN_DELAY) + await setBalance(vaultAddress, balanceBefore + (await vault.totalExitingAssets())) + + // claim exited assets + await vault.connect(admin).claimExitedAssets(positionTicket, timestamp, 0) + await setBalance(vaultAddress, balanceBefore) +} + export async function setAvgRewardPerSecond( dao: Signer, vault: EthVault, diff --git a/test/shared/types.ts b/test/shared/types.ts index 1c3633ab..f557a72f 100644 --- a/test/shared/types.ts +++ b/test/shared/types.ts @@ -1,3 +1,12 @@ +import { + EthErc20Vault, + EthFoxVault, + EthGenesisVault, + EthPrivErc20Vault, + EthPrivVault, + EthVault, +} from '../../typechain-types' + export type EthVaultInitParamsStruct = { capacity: bigint feePercent: number @@ -11,3 +20,11 @@ export type EthErc20VaultInitParamsStruct = { symbol: string metadataIpfsHash: string } + +export type VaultType = + | EthVault + | EthPrivVault + | EthErc20Vault + | EthPrivErc20Vault + | EthGenesisVault + | EthFoxVault diff --git a/test/shared/validators.ts b/test/shared/validators.ts index c8e24ff3..7870a6c2 100644 --- a/test/shared/validators.ts +++ b/test/shared/validators.ts @@ -4,7 +4,7 @@ import { ethers, network } from 'hardhat' import { Buffer } from 'buffer' import { BytesLike, Contract, ContractTransactionResponse, Signer } from 'ethers' import bls from 'bls-eth-wasm' -import { EthVault, Keeper, EthFoxVault } from '../../typechain-types' +import { EthVault, Keeper } from '../../typechain-types' import { EIP712Domain, KeeperUpdateExitSignaturesSig, @@ -13,6 +13,7 @@ import { VALIDATORS_MIN_ORACLES, } from './constants' import { getOraclesSignatures } from './fixtures' +import { VaultType } from './types' export const secretKeys = [ '0x2c66340f2d886f3fc4cfef10a802ddbaf4a37ffb49533b604f8a50804e8d198f', @@ -187,9 +188,7 @@ export function appendDepositData( return Buffer.concat([validator, DepositData.hashTreeRoot(depositData)]) } -export async function createEthValidatorsData( - vault: EthVault | EthFoxVault -): Promise { +export async function createEthValidatorsData(vault: VaultType): Promise { const validatorDeposit = ethers.parseEther('32') const validators = await createValidators(validatorDeposit, await vault.getAddress()) const tree = StandardMerkleTree.of( @@ -210,7 +209,7 @@ export async function getEthValidatorsSigningData( deadline: bigint, exitSignaturesIpfsHash: string, keeper: Keeper, - vault: EthVault | EthFoxVault, + vault: VaultType, validatorsRegistryRoot: BytesLike ) { return { @@ -278,7 +277,7 @@ export function getValidatorsMultiProof( } export async function registerEthValidator( - vault: EthVault | EthFoxVault, + vault: VaultType, keeper: Keeper, validatorsRegistry: Contract, admin: Signer From 25c3be639fc72b09b595fa6791e01dda4bac5dfd Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 13 Feb 2024 16:53:03 +0200 Subject: [PATCH 02/29] Fix exiting assets constructor arg --- contracts/vaults/ethereum/EthBlocklistErc20Vault.sol | 2 +- contracts/vaults/ethereum/EthBlocklistVault.sol | 2 +- contracts/vaults/ethereum/EthErc20Vault.sol | 2 +- contracts/vaults/ethereum/EthGenesisVault.sol | 2 +- contracts/vaults/ethereum/EthPrivErc20Vault.sol | 2 +- contracts/vaults/ethereum/EthPrivVault.sol | 2 +- contracts/vaults/ethereum/EthVault.sol | 6 +++--- contracts/vaults/ethereum/custom/EthFoxVault.sol | 6 +++--- contracts/vaults/modules/VaultEnterExit.sol | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol index 86cefbc3..b90a82f8 100644 --- a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -35,7 +35,7 @@ contract EthBlocklistErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol index cac02670..91fb0245 100644 --- a/contracts/vaults/ethereum/EthBlocklistVault.sol +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -29,7 +29,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthErc20Vault.sol b/contracts/vaults/ethereum/EthErc20Vault.sol index 19226156..c4efd9c3 100644 --- a/contracts/vaults/ethereum/EthErc20Vault.sol +++ b/contracts/vaults/ethereum/EthErc20Vault.sol @@ -53,7 +53,7 @@ contract EthErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index f502a769..c49a8531 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -45,7 +45,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { * @param sharedMevEscrow The address of the shared MEV escrow * @param poolEscrow The address of the pool escrow from StakeWise v2 * @param rewardEthToken The address of the rETH2 token from StakeWise v2 - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index f85d4d71..c18e8861 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -30,7 +30,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index 9d8e014f..159c7a28 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -29,7 +29,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( diff --git a/contracts/vaults/ethereum/EthVault.sol b/contracts/vaults/ethereum/EthVault.sol index 1b609ba2..68689eca 100644 --- a/contracts/vaults/ethereum/EthVault.sol +++ b/contracts/vaults/ethereum/EthVault.sol @@ -49,7 +49,7 @@ contract EthVault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitedAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( @@ -59,10 +59,10 @@ contract EthVault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - uint256 exitedAssetsClaimDelay + uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultEnterExit(exitedAssetsClaimDelay) + VaultEnterExit(exitingAssetsClaimDelay) VaultOsToken(osTokenVaultController, osTokenConfig) VaultMev(sharedMevEscrow) { diff --git a/contracts/vaults/ethereum/custom/EthFoxVault.sol b/contracts/vaults/ethereum/custom/EthFoxVault.sol index 1538fe56..99d524a8 100644 --- a/contracts/vaults/ethereum/custom/EthFoxVault.sol +++ b/contracts/vaults/ethereum/custom/EthFoxVault.sol @@ -46,7 +46,7 @@ contract EthFoxVault is * @param _vaultsRegistry The address of the VaultsRegistry contract * @param _validatorsRegistry The contract address used for registering validators in beacon chain * @param sharedMevEscrow The address of the shared MEV escrow - * @param exitedAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor( @@ -54,10 +54,10 @@ contract EthFoxVault is address _vaultsRegistry, address _validatorsRegistry, address sharedMevEscrow, - uint256 exitedAssetsClaimDelay + uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultEnterExit(exitedAssetsClaimDelay) + VaultEnterExit(exitingAssetsClaimDelay) VaultMev(sharedMevEscrow) { _disableInitializers(); diff --git a/contracts/vaults/modules/VaultEnterExit.sol b/contracts/vaults/modules/VaultEnterExit.sol index 523624eb..ee68324a 100644 --- a/contracts/vaults/modules/VaultEnterExit.sol +++ b/contracts/vaults/modules/VaultEnterExit.sol @@ -27,7 +27,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, * its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage. - * @param exitingAssetsClaimDelay The minimum delay after which the assets can be claimed after joining the exit queue + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor constructor(uint256 exitingAssetsClaimDelay) { From 212f30ec845f2c9291c5286929d90b37daa92912 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 28 Feb 2024 10:12:25 +0200 Subject: [PATCH 03/29] Move genesis vault legacy rewards update to _processTotalAssetsDelta --- abi/IEthBlocklistErc20Vault.json | 50 +++++++++++++ abi/IEthBlocklistVault.json | 50 +++++++++++++ abi/IEthErc20Vault.json | 50 +++++++++++++ abi/IEthFoxVault.json | 50 +++++++++++++ abi/IEthGenesisVault.json | 50 +++++++++++++ abi/{IPoolEscrow.json => IEthPoolEscrow.json} | 0 abi/IEthPrivErc20Vault.json | 50 +++++++++++++ abi/IEthPrivVault.json | 50 +++++++++++++ abi/IEthVault.json | 50 +++++++++++++ abi/IVaultEnterExit.json | 50 +++++++++++++ abi/IVaultEthStaking.json | 50 +++++++++++++ abi/IVaultMev.json | 13 ++++ abi/IVaultOsToken.json | 50 +++++++++++++ abi/IVaultState.json | 13 ++++ abi/IVaultToken.json | 50 +++++++++++++ abi/IVaultValidators.json | 13 ++++ .../{IPoolEscrow.sol => IEthPoolEscrow.sol} | 6 +- contracts/interfaces/IVaultEnterExit.sol | 11 +++ contracts/interfaces/IVaultState.sol | 6 ++ contracts/mocks/PoolEscrowMock.sol | 6 +- contracts/vaults/ethereum/EthGenesisVault.sol | 70 +++++++++++-------- contracts/vaults/modules/VaultEnterExit.sol | 10 +-- contracts/vaults/modules/VaultState.sol | 21 +++--- test/EthGenesisVault.spec.ts | 30 +++++++- test/EthVault.multicall.spec.ts | 2 +- test/EthVault.withdraw.spec.ts | 24 +++---- .../EthBlocklistErc20Vault.spec.ts.snap | 2 +- .../EthBlocklistVault.spec.ts.snap | 2 +- test/__snapshots__/EthErc20Vault.spec.ts.snap | 2 +- test/__snapshots__/EthFoxVault.spec.ts.snap | 2 +- .../EthGenesisVault.spec.ts.snap | 19 +++-- .../EthPrivErc20Vault.spec.ts.snap | 2 +- .../EthVault.deposit.spec.ts.snap | 6 +- .../EthVault.multicall.spec.ts.snap | 4 +- .../EthVault.register.spec.ts.snap | 4 +- .../EthVault.settings.spec.ts.snap | 2 +- .../__snapshots__/EthVault.state.spec.ts.snap | 6 +- .../EthVault.whitelist.spec.ts.snap | 4 +- .../EthVault.withdraw.spec.ts.snap | 8 +-- test/__snapshots__/KeeperRewards.spec.ts.snap | 12 ++-- .../KeeperValidators.spec.ts.snap | 8 +-- .../__snapshots__/RewardSplitter.spec.ts.snap | 6 +- 42 files changed, 811 insertions(+), 103 deletions(-) rename abi/{IPoolEscrow.json => IEthPoolEscrow.json} (100%) rename contracts/interfaces/{IPoolEscrow.sol => IEthPoolEscrow.sol} (95%) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index 986ea4c5..b9d51104 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -164,6 +164,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -410,6 +416,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1110,6 +1147,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index 77ccfcde..315ea296 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -139,6 +139,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -385,6 +391,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -892,6 +929,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index a6c94340..a6b58147 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -120,6 +120,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -366,6 +372,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1021,6 +1058,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index b7c90a72..24f53cc9 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -176,6 +176,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -274,6 +280,37 @@ "name": "MetadataUpdated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -710,6 +747,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index ffef15db..1f019294 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -397,6 +403,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -890,6 +927,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IPoolEscrow.json b/abi/IEthPoolEscrow.json similarity index 100% rename from abi/IPoolEscrow.json rename to abi/IEthPoolEscrow.json diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 26f443ca..9c31db11 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -120,6 +120,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -366,6 +372,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1078,6 +1115,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index 765b48b9..69b5ce12 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -341,6 +347,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -860,6 +897,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IEthVault.json b/abi/IEthVault.json index b99791c4..70f49211 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -341,6 +347,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -803,6 +840,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IVaultEnterExit.json b/abi/IVaultEnterExit.json index 4648c227..40e975a1 100644 --- a/abi/IVaultEnterExit.json +++ b/abi/IVaultEnterExit.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -174,6 +180,37 @@ "name": "MetadataUpdated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "inputs": [], "name": "admin", @@ -406,6 +443,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index 95af2719..3dee0cda 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -193,6 +199,37 @@ "name": "MetadataUpdated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -507,6 +544,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "receiveFromMevEscrow", diff --git a/abi/IVaultMev.json b/abi/IVaultMev.json index 59aaee4c..fedf4cbf 100644 --- a/abi/IVaultMev.json +++ b/abi/IVaultMev.json @@ -216,6 +216,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/IVaultOsToken.json b/abi/IVaultOsToken.json index 0dcfe754..657628a4 100644 --- a/abi/IVaultOsToken.json +++ b/abi/IVaultOsToken.json @@ -95,6 +95,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -322,6 +328,37 @@ "name": "OsTokenRedeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "inputs": [], "name": "admin", @@ -644,6 +681,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/IVaultState.json b/abi/IVaultState.json index 1dd827b8..53dc43c1 100644 --- a/abi/IVaultState.json +++ b/abi/IVaultState.json @@ -203,6 +203,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/IVaultToken.json b/abi/IVaultToken.json index 4a437759..6cabfd64 100644 --- a/abi/IVaultToken.json +++ b/abi/IVaultToken.json @@ -120,6 +120,12 @@ "name": "receiver", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "prevPositionTicket", + "type": "uint256" + }, { "indexed": false, "internalType": "uint256", @@ -199,6 +205,37 @@ "name": "MetadataUpdated", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Redeemed", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -624,6 +661,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/IVaultValidators.json b/abi/IVaultValidators.json index 60229b1b..9baee071 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -267,6 +267,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/contracts/interfaces/IPoolEscrow.sol b/contracts/interfaces/IEthPoolEscrow.sol similarity index 95% rename from contracts/interfaces/IPoolEscrow.sol rename to contracts/interfaces/IEthPoolEscrow.sol index 7401b255..62e9070e 100644 --- a/contracts/interfaces/IPoolEscrow.sol +++ b/contracts/interfaces/IEthPoolEscrow.sol @@ -3,12 +3,12 @@ pragma solidity 0.8.22; /** - * @title IPoolEscrow + * @title IEthPoolEscrow * @author StakeWise * @dev Copied from https://github.com/stakewise/contracts/blob/master/contracts/interfaces/IPoolEscrow.sol - * @notice Defines the interface for the PoolEscrow contract + * @notice Defines the interface for the PoolEscrow contract on Ethereum */ -interface IPoolEscrow { +interface IEthPoolEscrow { /** * @notice Event for tracking withdrawn ether * @param sender The address of the transaction sender diff --git a/contracts/interfaces/IVaultEnterExit.sol b/contracts/interfaces/IVaultEnterExit.sol index 359dd7ac..f12db10a 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -26,6 +26,15 @@ interface IVaultEnterExit is IVaultState { address referrer ); + /** + * @notice Event emitted on redeem + * @param owner The address that owns the shares + * @param receiver The address that received withdrawn assets + * @param assets The total number of withdrawn assets + * @param shares The total number of withdrawn shares + */ + event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); + /** * @notice Event emitted on shares added to the exit queue * @param owner The address that owns the shares @@ -43,11 +52,13 @@ interface IVaultEnterExit is IVaultState { /** * @notice Event emitted on claim of the exited assets * @param receiver The address that has received withdrawn assets + * @param prevPositionTicket The exit queue ticket received after the `enterExitQueue` call * @param newPositionTicket The new exit queue ticket in case not all the assets were withdrawn. Otherwise 0. * @param withdrawnAssets The total number of assets withdrawn */ event ExitedAssetsClaimed( address indexed receiver, + uint256 prevPositionTicket, uint256 newPositionTicket, uint256 withdrawnAssets ); diff --git a/contracts/interfaces/IVaultState.sol b/contracts/interfaces/IVaultState.sol index e7cfae3b..45815baf 100644 --- a/contracts/interfaces/IVaultState.sol +++ b/contracts/interfaces/IVaultState.sol @@ -26,6 +26,12 @@ interface IVaultState is IVaultFee { */ event FeeSharesMinted(address receiver, uint256 shares, uint256 assets); + /** + * @notice Queued Shares + * @return The total number of shares queued for exit + */ + function queuedShares() external view returns (uint128); + /** * @notice Total assets in the Vault * @return The total amount of the underlying asset that is "managed" by Vault diff --git a/contracts/mocks/PoolEscrowMock.sol b/contracts/mocks/PoolEscrowMock.sol index b9c0b3d4..51929822 100644 --- a/contracts/mocks/PoolEscrowMock.sol +++ b/contracts/mocks/PoolEscrowMock.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.22; -import '@openzeppelin/contracts/utils/Address.sol'; -import '../interfaces/IPoolEscrow.sol'; +import {Address} from '@openzeppelin/contracts/utils/Address.sol'; +import {IEthPoolEscrow} from '../interfaces/IEthPoolEscrow.sol'; /** * @title PoolEscrowMock @@ -13,7 +13,7 @@ import '../interfaces/IPoolEscrow.sol'; * https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.2/specs/phase0/validator.md#eth1_address_withdrawal_prefix * using the address of this contract as a destination. */ -contract PoolEscrowMock is IPoolEscrow { +contract PoolEscrowMock is IEthPoolEscrow { using Address for address payable; // @dev The address of the current contract owner. diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index c49a8531..eaba52e6 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -6,7 +6,7 @@ import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Ini import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; -import {IPoolEscrow} from '../../interfaces/IPoolEscrow.sol'; +import {IEthPoolEscrow} from '../../interfaces/IEthPoolEscrow.sol'; import {IEthGenesisVault} from '../../interfaces/IEthGenesisVault.sol'; import {IRewardEthToken} from '../../interfaces/IRewardEthToken.sol'; import {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol'; @@ -26,7 +26,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { uint8 private constant _version = 2; /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - IPoolEscrow private immutable _poolEscrow; + IEthPoolEscrow private immutable _poolEscrow; /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IRewardEthToken private immutable _rewardEthToken; @@ -69,7 +69,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { exitingAssetsClaimDelay ) { - _poolEscrow = IPoolEscrow(poolEscrow); + _poolEscrow = IEthPoolEscrow(poolEscrow); _rewardEthToken = IRewardEthToken(rewardEthToken); } @@ -131,31 +131,8 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { } } - // fetch total assets controlled by legacy pool - uint256 legacyPrincipal = _rewardEthToken.totalAssets() - _rewardEthToken.totalPenalty(); - - // calculate total principal - uint256 totalPrincipal = _totalAssets + legacyPrincipal; - if (totalAssetsDelta < 0) { - // calculate and update penalty for legacy pool - int256 legacyPenalty = SafeCast.toInt256( - Math.mulDiv(uint256(-totalAssetsDelta), legacyPrincipal, totalPrincipal) - ); - _rewardEthToken.updateTotalRewards(-legacyPenalty); - // deduct penalty from total assets delta - totalAssetsDelta += legacyPenalty; - } else { - // calculate and update reward for legacy pool - int256 legacyReward = SafeCast.toInt256( - Math.mulDiv(uint256(totalAssetsDelta), legacyPrincipal, totalPrincipal) - ); - _rewardEthToken.updateTotalRewards(legacyReward); - // deduct reward from total assets delta - totalAssetsDelta -= legacyReward; - } - - // process total assets delta if it has changed - if (totalAssetsDelta != 0) _processTotalAssetsDelta(totalAssetsDelta); + // process total assets delta + _processTotalAssetsDelta(totalAssetsDelta); // update exit queue every time new update is harvested if (harvested) _updateExitQueue(); @@ -191,6 +168,43 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { } } + /// @inheritdoc VaultState + function _processTotalAssetsDelta(int256 totalAssetsDelta) internal override { + // skip processing if there is no change in assets + if (totalAssetsDelta == 0) return; + + // fetch total assets controlled by legacy pool + uint256 legacyPrincipal = _rewardEthToken.totalAssets() - _rewardEthToken.totalPenalty(); + if (legacyPrincipal == 0) { + // legacy pool has no assets, process total assets delta as usual + super._processTotalAssetsDelta(totalAssetsDelta); + return; + } + + // calculate total principal + uint256 totalPrincipal = _totalAssets + legacyPrincipal; + if (totalAssetsDelta < 0) { + // calculate and update penalty for legacy pool + int256 legacyPenalty = SafeCast.toInt256( + Math.mulDiv(uint256(-totalAssetsDelta), legacyPrincipal, totalPrincipal) + ); + _rewardEthToken.updateTotalRewards(-legacyPenalty); + // deduct penalty from total assets delta + totalAssetsDelta += legacyPenalty; + } else { + // calculate and update reward for legacy pool + int256 legacyReward = SafeCast.toInt256( + Math.mulDiv(uint256(totalAssetsDelta), legacyPrincipal, totalPrincipal) + ); + _rewardEthToken.updateTotalRewards(legacyReward); + // deduct reward from total assets delta + totalAssetsDelta -= legacyReward; + } + + // process total assets delta + super._processTotalAssetsDelta(totalAssetsDelta); + } + /// @inheritdoc VaultEnterExit function _transferVaultAssets( address receiver, diff --git a/contracts/vaults/modules/VaultEnterExit.sol b/contracts/vaults/modules/VaultEnterExit.sol index ee68324a..7dbdcdc7 100644 --- a/contracts/vaults/modules/VaultEnterExit.sol +++ b/contracts/vaults/modules/VaultEnterExit.sol @@ -36,7 +36,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, /// @inheritdoc IVaultEnterExit function getExitQueueIndex(uint256 positionTicket) external view override returns (int256) { - if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + if (_exitQueue.isV1Position(queuedShares, positionTicket)) { uint256 checkpointIdx = _exitQueue.getCheckpointIndex(positionTicket); return checkpointIdx < _exitQueue.checkpoints.length ? int256(checkpointIdx) : -1; } @@ -71,7 +71,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, if (exitingTickets == 0) return (0, 0, 0); if (block.timestamp < timestamp + _exitingAssetsClaimDelay) return (exitingTickets, 0, 0); - if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + if (_exitQueue.isV1Position(queuedShares, positionTicket)) { // calculate exited assets in V1 exit queue (exitedTickets, exitedAssets) = _exitQueue.calculateExitedAssets( exitQueueIndex, @@ -100,7 +100,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, ); if (exitedTickets == 0 || exitedAssets == 0) revert Errors.ExitRequestNotProcessed(); - if (_exitQueue.isV1Position(_queuedShares, positionTicket)) { + if (_exitQueue.isV1Position(queuedShares, positionTicket)) { // update unclaimed assets _unclaimedAssets -= SafeCast.toUint128(exitedAssets); } else { @@ -126,7 +126,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, // transfer assets to the receiver _transferVaultAssets(msg.sender, exitedAssets); - emit ExitedAssetsClaimed(msg.sender, newPositionTicket, exitedAssets); + emit ExitedAssetsClaimed(msg.sender, positionTicket, newPositionTicket, exitedAssets); } function _calculateExitedTickets( @@ -231,7 +231,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, function _getTotalExitableTickets() private view returns (uint256) { // calculate available assets uint256 availableAssets = _vaultAssets() - _unclaimedAssets; - uint256 queuedAssets = convertToAssets(_queuedShares); + uint256 queuedAssets = convertToAssets(queuedShares); if (queuedAssets > 0) { unchecked { // cannot underflow as availableAssets >= queuedV1Assets diff --git a/contracts/vaults/modules/VaultState.sol b/contracts/vaults/modules/VaultState.sol index f04da2b2..f4c44db1 100644 --- a/contracts/vaults/modules/VaultState.sol +++ b/contracts/vaults/modules/VaultState.sol @@ -23,7 +23,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint128 internal _totalShares; uint128 internal _totalAssets; - uint128 internal _queuedShares; + uint128 public override queuedShares; uint128 internal _unclaimedAssets; ExitQueue.History internal _exitQueue; @@ -77,7 +77,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault unchecked { // calculate assets that are reserved by users who queued for exit // cannot overflow as it is capped with underlying asset total supply - uint256 reservedAssets = convertToAssets(_queuedShares) + + uint256 reservedAssets = convertToAssets(queuedShares) + totalExitingAssets + _unclaimedAssets; return vaultAssets > reservedAssets ? vaultAssets - reservedAssets : 0; @@ -97,7 +97,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault (int256 totalAssetsDelta, bool harvested) = _harvestAssets(harvestParams); // process total assets delta if it has changed - if (totalAssetsDelta != 0) _processTotalAssetsDelta(totalAssetsDelta); + _processTotalAssetsDelta(totalAssetsDelta); // update exit queue every time new update is harvested if (harvested) _updateExitQueue(); @@ -107,7 +107,10 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault * @dev Internal function for processing rewards and penalties * @param totalAssetsDelta The number of assets earned or lost */ - function _processTotalAssetsDelta(int256 totalAssetsDelta) internal { + function _processTotalAssetsDelta(int256 totalAssetsDelta) internal virtual { + // skip processing if there is no change in assets + if (totalAssetsDelta == 0) return; + // SLOAD to memory uint256 newTotalAssets = _totalAssets; if (totalAssetsDelta < 0) { @@ -182,14 +185,14 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault */ function _updateExitQueue() internal virtual returns (uint256 burnedShares) { // SLOAD to memory - uint256 queuedShares = _queuedShares; - if (queuedShares == 0) return 0; + uint256 _queuedShares = queuedShares; + if (_queuedShares == 0) return 0; // calculate the amount of assets that can be exited uint256 unclaimedAssets = _unclaimedAssets; uint256 exitedAssets = Math.min( _vaultAssets() - unclaimedAssets, - convertToAssets(queuedShares) + convertToAssets(_queuedShares) ); if (exitedAssets == 0) return 0; @@ -198,7 +201,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault if (burnedShares == 0) return 0; // update queued shares and unclaimed assets - _queuedShares = SafeCast.toUint128(queuedShares - burnedShares); + queuedShares = SafeCast.toUint128(_queuedShares - burnedShares); _unclaimedAssets = SafeCast.toUint128(unclaimedAssets + exitedAssets); // push checkpoint so that exited assets could be claimed @@ -314,7 +317,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault */ function __VaultState_initV2() internal onlyInitializing { // set initial value for total exited tickets - _totalExitedTickets = _exitQueue.getLatestTotalTickets() + _queuedShares; + _totalExitedTickets = _exitQueue.getLatestTotalTickets() + queuedShares; } /** diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 08cb4340..b5dd6b98 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -253,7 +253,9 @@ describe('EthGenesisVault', () => { await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, poolEscrowBalance + vaultBalance) - await expect(tx).to.emit(vault, 'ExitedAssetsClaimed').withArgs(other.address, 0, assets) + await expect(tx) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(other.address, positionTicket, 0, assets) expect(await ethers.provider.getBalance(await poolEscrow.getAddress())).to.eq(0) await snapshotGasCost(tx) }) @@ -389,6 +391,32 @@ describe('EthGenesisVault', () => { await snapshotGasCost(receipt) }) + it('skips updating legacy with zero total assets', async () => { + await acceptPoolEscrowOwnership() + await rewardEthToken.setTotalStaked(0n) + await rewardEthToken.setTotalRewards(0n) + await rewardEthToken.setTotalPenalty(0n) + + const reward = ethers.parseEther('5') + const unlockedMevReward = 0n + + const vaultReward = getHarvestParams(await vault.getAddress(), reward, unlockedMevReward) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + + const totalLegacyAssetsBefore = await rewardEthToken.totalAssets() + const totalVaultAssetsBefore = await vault.totalAssets() + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + expect(await rewardEthToken.totalAssets()).to.eq(totalLegacyAssetsBefore) + expect(await vault.totalAssets()).to.eq(totalVaultAssetsBefore + reward) + await snapshotGasCost(receipt) + }) + it('fails when pool escrow ownership not accepted', async () => { const [vault] = await createGenesisVault( admin, diff --git a/test/EthVault.multicall.spec.ts b/test/EthVault.multicall.spec.ts index ea7d445e..3575b35c 100644 --- a/test/EthVault.multicall.spec.ts +++ b/test/EthVault.multicall.spec.ts @@ -144,7 +144,7 @@ describe('EthVault - multicall', () => { receipt = await vault.connect(sender).multicall(calls) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(sender.address, 0, userAssets - 1n) // 1 wei is left in the vault + .withArgs(sender.address, queueTicket, 0, userAssets - 1n) // 1 wei is left in the vault await snapshotGasCost(receipt) }) diff --git a/test/EthVault.withdraw.spec.ts b/test/EthVault.withdraw.spec.ts index 75f7ba83..72220a39 100644 --- a/test/EthVault.withdraw.spec.ts +++ b/test/EthVault.withdraw.spec.ts @@ -147,7 +147,7 @@ describe('EthVault - withdraw', () => { const balanceBefore = await ethers.provider.getBalance(holderV2.address) await expect(vault.connect(holderV2).claimExitedAssets(positionTicket, timestamp, 0n)) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV2.address, 0n, holderV2Assets) + .withArgs(holderV2.address, positionTicket, 0n, holderV2Assets) expect(await ethers.provider.getBalance(holderV2.address)).to.be.greaterThan( balanceBefore + holderV2Assets - parseEther('0.0001') // gas ) @@ -688,10 +688,10 @@ describe('EthVault - withdraw', () => { ) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV1.address, 0n, holderV1Assets) + .withArgs(holderV1.address, positionTicketV1, 0n, holderV1Assets) await expect(vault.connect(holderV2).claimExitedAssets(positionTicketV2, timestampV2, 0n)) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV2.address, 0n, halfHolderV2Assets + halfSecurityDeposit) + .withArgs(holderV2.address, positionTicketV2, 0n, halfHolderV2Assets + halfSecurityDeposit) expect(await vault.totalExitingAssets()).to.be.eq(0) }) @@ -736,7 +736,7 @@ describe('EthVault - withdraw', () => { ) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV2.address, 0n, halfHolderV2Assets) + .withArgs(holderV2.address, positionTicket, 0n, halfHolderV2Assets) expect(await vault.totalExitingAssets()).to.be.eq(0) }) @@ -751,7 +751,7 @@ describe('EthVault - withdraw', () => { .claimExitedAssets(positionTicketV1, timestampV1, checkpointIndex) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV1.address, 0, holderV1Assets) + .withArgs(holderV1.address, positionTicketV1, 0, holderV1Assets) const tx = (await receipt.wait()) as any const gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) expect(await ethers.provider.getBalance(holderV1.address)).to.be.eq( @@ -788,7 +788,7 @@ describe('EthVault - withdraw', () => { await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV1.address, 0, holderV1Assets) + .withArgs(holderV1.address, positionTicketV1, 0, holderV1Assets) const tx = (await receipt.wait()) as any const gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) @@ -820,7 +820,7 @@ describe('EthVault - withdraw', () => { const newPositionTicket = validatorDeposit + halfHolderShares await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV1.address, newPositionTicket, halfHolderAssets) + .withArgs(holderV1.address, positionTicketV1, newPositionTicket, halfHolderAssets) let tx = (await receipt.wait()) as any let gasUsed = BigInt(tx.cumulativeGasUsed * tx.gasPrice) @@ -846,7 +846,7 @@ describe('EthVault - withdraw', () => { .claimExitedAssets(newPositionTicket, timestampV1, newCheckpointIndex) await expect(receipt) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(holderV1.address, 0, halfHolderAssets) + .withArgs(holderV1.address, newPositionTicket, 0, halfHolderAssets) tx = (await receipt.wait()) as any gasUsed += BigInt(tx.cumulativeGasUsed * tx.gasPrice) @@ -1208,7 +1208,7 @@ describe('EthVault - withdraw', () => { vault.connect(bob).claimExitedAssets(bobPositionTicket, bobTimestamp, bobCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(bob.address, bobPositionTicket + 3779n, 3779n) + .withArgs(bob.address, bobPositionTicket, bobPositionTicket + 3779n, 3779n) bobPositionTicket += 3779n vaultLiquidAssets -= 3779n @@ -1223,7 +1223,7 @@ describe('EthVault - withdraw', () => { .claimExitedAssets(alicePositionTicket, aliceTimestamp, aliceCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(alice.address, 0n, 1821) + .withArgs(alice.address, alicePositionTicket, 0n, 1821) vaultLiquidAssets -= 1821n totalExitingAssets -= 1821n @@ -1258,7 +1258,7 @@ describe('EthVault - withdraw', () => { vault.connect(bob).claimExitedAssets(bobPositionTicket, bobTimestamp, bobCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(bob.address, 0, 4221) + .withArgs(bob.address, bobPositionTicket, 0, 4221) vaultLiquidAssets -= 4221n totalExitingAssets -= 4221n @@ -1272,7 +1272,7 @@ describe('EthVault - withdraw', () => { .claimExitedAssets(alicePositionTicket, aliceTimestamp, aliceCheckpointIdx) ) .to.emit(vault, 'ExitedAssetsClaimed') - .withArgs(alice.address, 0, 6824) + .withArgs(alice.address, alicePositionTicket, 0, 6824) vaultLiquidAssets -= 6824n totalExitingAssets -= 6824n await checkVaultState() diff --git a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap index 764c4e4c..fc3b7b90 100644 --- a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71149, + "gasUsed": 71171, } `; diff --git a/test/__snapshots__/EthBlocklistVault.spec.ts.snap b/test/__snapshots__/EthBlocklistVault.spec.ts.snap index 1e5fea86..2de3c991 100644 --- a/test/__snapshots__/EthBlocklistVault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistVault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69056, + "gasUsed": 69078, } `; diff --git a/test/__snapshots__/EthErc20Vault.spec.ts.snap b/test/__snapshots__/EthErc20Vault.spec.ts.snap index 70aa490e..ad24c40c 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthErc20Vault deposit emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68804, + "gasUsed": 68826, } `; diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index 669281f9..edc68163 100644 --- a/test/__snapshots__/EthFoxVault.spec.ts.snap +++ b/test/__snapshots__/EthFoxVault.spec.ts.snap @@ -17,7 +17,7 @@ Object { exports[`EthFoxVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68946, + "gasUsed": 68968, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index c1abab46..9c50c27a 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -17,41 +17,48 @@ Object { exports[`EthGenesisVault pulls assets on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 76981, + "gasUsed": 77231, } `; exports[`EthGenesisVault pulls assets on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638161, + "gasUsed": 638183, } `; exports[`EthGenesisVault pulls assets on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301759, + "gasUsed": 301781, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150215, + "gasUsed": 150242, +} +`; + +exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 145811, } `; exports[`EthGenesisVault update state splits penalty between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 119905, + "gasUsed": 119951, } `; exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167315, + "gasUsed": 167342, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index d605e28c..62cd2081 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71137, + "gasUsed": 71159, } `; diff --git a/test/__snapshots__/EthVault.deposit.spec.ts.snap b/test/__snapshots__/EthVault.deposit.spec.ts.snap index fcc3d6d8..f9585fe0 100644 --- a/test/__snapshots__/EthVault.deposit.spec.ts.snap +++ b/test/__snapshots__/EthVault.deposit.spec.ts.snap @@ -3,14 +3,14 @@ exports[`EthVault - deposit empty vault: no assets & no shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66711, + "gasUsed": 66733, } `; exports[`EthVault - deposit full vault: assets & shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66711, + "gasUsed": 66733, } `; @@ -24,6 +24,6 @@ Object { exports[`EthVault - deposit full vault: assets & shares update state and deposit 1`] = ` Object { "calldataByteLength": 260, - "gasUsed": 155335, + "gasUsed": 155354, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index a70587f8..1f325696 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168267, + "gasUsed": 168286, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 109586, + "gasUsed": 109839, } `; diff --git a/test/__snapshots__/EthVault.register.spec.ts.snap b/test/__snapshots__/EthVault.register.spec.ts.snap index 38f9e0da..18bd2761 100644 --- a/test/__snapshots__/EthVault.register.spec.ts.snap +++ b/test/__snapshots__/EthVault.register.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3332, - "gasUsed": 673647, + "gasUsed": 673669, } `; exports[`EthVault - register single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 324126, + "gasUsed": 324148, } `; diff --git a/test/__snapshots__/EthVault.settings.spec.ts.snap b/test/__snapshots__/EthVault.settings.spec.ts.snap index 076dfd07..35a28b8d 100644 --- a/test/__snapshots__/EthVault.settings.spec.ts.snap +++ b/test/__snapshots__/EthVault.settings.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthVault - settings fee recipient can update 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 43992, + "gasUsed": 44014, } `; diff --git a/test/__snapshots__/EthVault.state.spec.ts.snap b/test/__snapshots__/EthVault.state.spec.ts.snap index 86f056d3..aaf93a87 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthVault - state allocates fee to recipient when delta is above zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117567, + "gasUsed": 117586, } `; exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117653, + "gasUsed": 117672, } `; exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 107206, + "gasUsed": 107225, } `; diff --git a/test/__snapshots__/EthVault.whitelist.spec.ts.snap b/test/__snapshots__/EthVault.whitelist.spec.ts.snap index 0fff6a6c..694e10bd 100644 --- a/test/__snapshots__/EthVault.whitelist.spec.ts.snap +++ b/test/__snapshots__/EthVault.whitelist.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthVault - whitelist deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69044, + "gasUsed": 69066, } `; @@ -17,7 +17,7 @@ Object { exports[`EthVault - whitelist set whitelister admin can update whitelister 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 36223, + "gasUsed": 36245, } `; diff --git a/test/__snapshots__/EthVault.withdraw.spec.ts.snap b/test/__snapshots__/EthVault.withdraw.spec.ts.snap index 0c944164..2e446e0e 100644 --- a/test/__snapshots__/EthVault.withdraw.spec.ts.snap +++ b/test/__snapshots__/EthVault.withdraw.spec.ts.snap @@ -3,28 +3,28 @@ exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 75784, + "gasUsed": 76025, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48640, + "gasUsed": 48843, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in single transaction 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 51208, + "gasUsed": 51461, } `; exports[`EthVault - withdraw claim exited assets for single user in single checkpoint 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48640, + "gasUsed": 48843, } `; diff --git a/test/__snapshots__/KeeperRewards.spec.ts.snap b/test/__snapshots__/KeeperRewards.spec.ts.snap index 458c5911..0351ad61 100644 --- a/test/__snapshots__/KeeperRewards.spec.ts.snap +++ b/test/__snapshots__/KeeperRewards.spec.ts.snap @@ -3,42 +3,42 @@ exports[`KeeperRewards harvest (own escrow) succeeds for latest rewards root 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 111388, + "gasUsed": 111407, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 113542, + "gasUsed": 113561, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 74309, + "gasUsed": 74328, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for latest rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 143942, + "gasUsed": 143961, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 146096, + "gasUsed": 146115, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 90476, + "gasUsed": 90495, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index a47560d8..426a2016 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -3,28 +3,28 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 679964, + "gasUsed": 679986, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 588370, + "gasUsed": 588392, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 330490, + "gasUsed": 330512, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1508, - "gasUsed": 276218, + "gasUsed": 276240, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index 94be549f..3652711d 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -3,7 +3,7 @@ exports[`RewardSplitter decrease shares owner can decrease shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 67079, + "gasUsed": 67101, } `; @@ -17,7 +17,7 @@ Object { exports[`RewardSplitter sync rewards anyone can sync rewards 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 73104, + "gasUsed": 73126, } `; @@ -31,6 +31,6 @@ Object { exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170678, + "gasUsed": 170719, } `; From 8b92b50be3437e92a5279902a401a037ebc4e661 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Fri, 1 Mar 2024 17:26:48 +0200 Subject: [PATCH 04/29] Remove ejectUser functions, change genesis withdrawal creds to pool escrow --- abi/IEthBlocklistErc20Vault.json | 13 -- abi/IEthBlocklistVault.json | 13 -- abi/IEthPrivErc20Vault.json | 13 -- abi/IEthPrivVault.json | 13 -- .../interfaces/IEthBlocklistErc20Vault.sol | 9 +- contracts/interfaces/IEthBlocklistVault.sol | 9 +- contracts/interfaces/IEthPrivErc20Vault.sol | 9 +- contracts/interfaces/IEthPrivVault.sol | 9 +- ...okenMock.sol => LegacyRewardTokenMock.sol} | 2 +- .../ethereum/EthBlocklistErc20Vault.sol | 24 --- .../vaults/ethereum/EthBlocklistVault.sol | 24 --- contracts/vaults/ethereum/EthGenesisVault.sol | 13 +- .../vaults/ethereum/EthPrivErc20Vault.sol | 24 --- contracts/vaults/ethereum/EthPrivVault.sol | 24 --- contracts/vaults/modules/VaultValidators.sol | 2 +- test/EthBlocklistErc20Vault.spec.ts | 117 +-------------- test/EthBlocklistVault.spec.ts | 117 +-------------- test/EthGenesisVault.spec.ts | 22 ++- test/EthPrivErc20Vault.spec.ts | 140 ++++-------------- test/EthPrivVault.spec.ts | 131 +--------------- test/EthVault.upgrade.spec.ts | 8 +- test/EthVault.withdraw.spec.ts | 4 +- test/VaultsRegistry.spec.ts | 4 +- .../EthBlocklistErc20Vault.spec.ts.snap | 30 +--- .../EthBlocklistVault.spec.ts.snap | 30 +--- .../EthGenesisVault.spec.ts.snap | 20 +-- .../EthPrivErc20Vault.spec.ts.snap | 29 +--- test/__snapshots__/EthPrivVault.spec.ts.snap | 28 ---- .../EthVault.deposit.spec.ts.snap | 2 +- .../EthVault.multicall.spec.ts.snap | 4 +- .../__snapshots__/EthVault.state.spec.ts.snap | 6 +- .../EthVault.whitelist.spec.ts.snap | 4 +- test/__snapshots__/KeeperRewards.spec.ts.snap | 12 +- .../__snapshots__/RewardSplitter.spec.ts.snap | 2 +- test/shared/contracts.ts | 2 +- test/shared/fixtures.ts | 70 +++++---- test/shared/rewards.ts | 9 +- test/shared/types.ts | 2 +- test/shared/validators.ts | 24 +-- 39 files changed, 161 insertions(+), 857 deletions(-) rename contracts/mocks/{RewardEthTokenMock.sol => LegacyRewardTokenMock.sol} (97%) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index b9d51104..7fd9f593 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -803,19 +803,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "ejectUser", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index 315ea296..bba88550 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -660,19 +660,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "ejectUser", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 9c31db11..00c4270b 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -771,19 +771,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "ejectUser", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index 69b5ce12..96a01dcc 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -628,19 +628,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "ejectUser", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/contracts/interfaces/IEthBlocklistErc20Vault.sol b/contracts/interfaces/IEthBlocklistErc20Vault.sol index 489d6b55..3f41f0f3 100644 --- a/contracts/interfaces/IEthBlocklistErc20Vault.sol +++ b/contracts/interfaces/IEthBlocklistErc20Vault.sol @@ -10,11 +10,4 @@ import {IEthErc20Vault} from './IEthErc20Vault.sol'; * @author StakeWise * @notice Defines the interface for the EthBlocklistErc20Vault contract */ -interface IEthBlocklistErc20Vault is IEthErc20Vault, IVaultBlocklist { - /** - * @notice Function for ejecting user from the vault. Can be called only by the blocklist manager. - * The user will be added to the blocklist and placed to the exit queue. - * @param user The address of the user - */ - function ejectUser(address user) external; -} +interface IEthBlocklistErc20Vault is IEthErc20Vault, IVaultBlocklist {} diff --git a/contracts/interfaces/IEthBlocklistVault.sol b/contracts/interfaces/IEthBlocklistVault.sol index e7df7331..35683da3 100644 --- a/contracts/interfaces/IEthBlocklistVault.sol +++ b/contracts/interfaces/IEthBlocklistVault.sol @@ -10,11 +10,4 @@ import {IEthVault} from './IEthVault.sol'; * @author StakeWise * @notice Defines the interface for the EthBlocklistVault contract */ -interface IEthBlocklistVault is IEthVault, IVaultBlocklist { - /** - * @notice Function for ejecting user from the vault. Can be called only by the blocklist manager. - * The user will be added to the blocklist and placed to the exit queue. - * @param user The address of the user - */ - function ejectUser(address user) external; -} +interface IEthBlocklistVault is IEthVault, IVaultBlocklist {} diff --git a/contracts/interfaces/IEthPrivErc20Vault.sol b/contracts/interfaces/IEthPrivErc20Vault.sol index 7f23e8b4..0fbab335 100644 --- a/contracts/interfaces/IEthPrivErc20Vault.sol +++ b/contracts/interfaces/IEthPrivErc20Vault.sol @@ -10,11 +10,4 @@ import {IEthErc20Vault} from './IEthErc20Vault.sol'; * @author StakeWise * @notice Defines the interface for the EthPrivErc20Vault contract */ -interface IEthPrivErc20Vault is IEthErc20Vault, IVaultWhitelist { - /** - * @notice Function for ejecting user from the vault. Can only be called by the whitelister. - * The user will be removed from the whitelist and placed to the exit queue. - * @param user The address of the user - */ - function ejectUser(address user) external; -} +interface IEthPrivErc20Vault is IEthErc20Vault, IVaultWhitelist {} diff --git a/contracts/interfaces/IEthPrivVault.sol b/contracts/interfaces/IEthPrivVault.sol index 067cd8ae..75ef0117 100644 --- a/contracts/interfaces/IEthPrivVault.sol +++ b/contracts/interfaces/IEthPrivVault.sol @@ -10,11 +10,4 @@ import {IEthVault} from './IEthVault.sol'; * @author StakeWise * @notice Defines the interface for the EthPrivVault contract */ -interface IEthPrivVault is IEthVault, IVaultWhitelist { - /** - * @notice Function for ejecting user from the vault. Can only be called by the whitelister. - * The user will be removed from the whitelist and placed to the exit queue. - * @param user The address of the user - */ - function ejectUser(address user) external; -} +interface IEthPrivVault is IEthVault, IVaultWhitelist {} diff --git a/contracts/mocks/RewardEthTokenMock.sol b/contracts/mocks/LegacyRewardTokenMock.sol similarity index 97% rename from contracts/mocks/RewardEthTokenMock.sol rename to contracts/mocks/LegacyRewardTokenMock.sol index cf98f166..6f9afe10 100644 --- a/contracts/mocks/RewardEthTokenMock.sol +++ b/contracts/mocks/LegacyRewardTokenMock.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.22; import {Math} from '@openzeppelin/contracts/utils/math/Math.sol'; import {IEthGenesisVault} from '../interfaces/IEthGenesisVault.sol'; -contract RewardEthTokenMock { +contract LegacyRewardTokenMock { address public vault; uint256 public totalStaked; uint256 public totalRewards; diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol index b90a82f8..798181a5 100644 --- a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -102,30 +102,6 @@ contract EthBlocklistErc20Vault is return super.mintOsToken(receiver, osTokenShares, referrer); } - /// @inheritdoc IEthBlocklistErc20Vault - function ejectUser(address user) external override { - // add user to the blocklist - updateBlocklist(user, true); - - // fetch shares of the user - uint256 userShares = _balances[user]; - if (userShares == 0) return; - - // calculated shares that are locked due to minted osToken - uint256 lockedShares = _getLockedShares(user); - if (lockedShares >= userShares) return; - - // calculate shares to eject - uint256 ejectedShares; - unchecked { - // cannot underflow as lockedShares < userShares - ejectedShares = userShares - lockedShares; - } - - // eject shares that are not locked - _enterExitQueue(user, ejectedShares, user); - } - /// @inheritdoc IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { return keccak256('EthBlocklistErc20Vault'); diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol index 91fb0245..12385209 100644 --- a/contracts/vaults/ethereum/EthBlocklistVault.sol +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -96,30 +96,6 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock return super.mintOsToken(receiver, osTokenShares, referrer); } - /// @inheritdoc IEthBlocklistVault - function ejectUser(address user) external override { - // add user to blocklist - updateBlocklist(user, true); - - // fetch shares of the user - uint256 userShares = _balances[user]; - if (userShares == 0) return; - - // calculated shares that are locked due to minted osToken - uint256 lockedShares = _getLockedShares(user); - if (lockedShares >= userShares) return; - - // calculate shares to eject - uint256 ejectedShares; - unchecked { - // cannot underflow as lockedShares < userShares - ejectedShares = userShares - lockedShares; - } - - // eject shares that are not locked - _enterExitQueue(user, ejectedShares, user); - } - /// @inheritdoc IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthVault) returns (bytes32) { return keccak256('EthBlocklistVault'); diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index eaba52e6..67ac1676 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -210,7 +210,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { address receiver, uint256 assets ) internal virtual override(VaultEnterExit, VaultEthStaking) { - if (assets > super._vaultAssets()) _pullAssets(); + if (assets > super._vaultAssets()) _pullWithdrawals(); return super._transferVaultAssets(receiver, assets); } @@ -232,7 +232,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { function _registerSingleValidator( bytes calldata validator ) internal virtual override(VaultValidators, VaultEthStaking) { - _pullAssets(); + _pullWithdrawals(); super._registerSingleValidator(validator); } @@ -241,18 +241,23 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { bytes calldata validators, uint256[] calldata indexes ) internal virtual override(VaultValidators, VaultEthStaking) returns (bytes32[] memory leaves) { - _pullAssets(); + _pullWithdrawals(); return super._registerMultipleValidators(validators, indexes); } /** * @dev Pulls assets from pool escrow */ - function _pullAssets() private { + function _pullWithdrawals() private { uint256 escrowBalance = address(_poolEscrow).balance; if (escrowBalance != 0) _poolEscrow.withdraw(payable(this), escrowBalance); } + /// @inheritdoc VaultValidators + function _withdrawalCredentials() internal view override returns (bytes memory) { + return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(_poolEscrow)); + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index c18e8861..5867fef3 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -101,30 +101,6 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth return super.mintOsToken(receiver, osTokenShares, referrer); } - /// @inheritdoc IEthPrivErc20Vault - function ejectUser(address user) external override { - // remove user from the whitelist - updateWhitelist(user, false); - - // fetch shares of the user - uint256 userShares = _balances[user]; - if (userShares == 0) return; - - // calculated shares that are locked due to minted osToken - uint256 lockedShares = _getLockedShares(user); - if (lockedShares >= userShares) return; - - // calculate shares to eject - uint256 ejectedShares; - unchecked { - // cannot underflow as lockedShares < userShares - ejectedShares = userShares - lockedShares; - } - - // eject shares that are not locked - _enterExitQueue(user, ejectedShares, user); - } - /// @inheritdoc IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { return keccak256('EthPrivErc20Vault'); diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index 159c7a28..fbfa5938 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -100,30 +100,6 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault return super.mintOsToken(receiver, osTokenShares, referrer); } - /// @inheritdoc IEthPrivVault - function ejectUser(address user) external override { - // remove user from the whitelist - updateWhitelist(user, false); - - // fetch shares of the user - uint256 userShares = _balances[user]; - if (userShares == 0) return; - - // calculated shares that are locked due to minted osToken - uint256 lockedShares = _getLockedShares(user); - if (lockedShares >= userShares) return; - - // calculate shares to eject - uint256 ejectedShares; - unchecked { - // cannot underflow as lockedShares < userShares - ejectedShares = userShares - lockedShares; - } - - // eject shares that are not locked - _enterExitQueue(user, ejectedShares, user); - } - /// @inheritdoc IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthVault) returns (bytes32) { return keccak256('EthPrivVault'); diff --git a/contracts/vaults/modules/VaultValidators.sol b/contracts/vaults/modules/VaultValidators.sol index 8a54a73a..2899cbc2 100644 --- a/contracts/vaults/modules/VaultValidators.sol +++ b/contracts/vaults/modules/VaultValidators.sol @@ -157,7 +157,7 @@ abstract contract VaultValidators is * @dev Internal function for calculating Vault withdrawal credentials * @return The credentials used for the validators withdrawals */ - function _withdrawalCredentials() internal view returns (bytes memory) { + function _withdrawalCredentials() internal view virtual returns (bytes memory) { return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)); } diff --git a/test/EthBlocklistErc20Vault.spec.ts b/test/EthBlocklistErc20Vault.spec.ts index 013aa9df..964da341 100644 --- a/test/EthBlocklistErc20Vault.spec.ts +++ b/test/EthBlocklistErc20Vault.spec.ts @@ -1,11 +1,11 @@ import { ethers } from 'hardhat' -import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthBlocklistErc20Vault, + IKeeperRewards, Keeper, OsTokenVaultController, - IKeeperRewards, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -204,117 +204,4 @@ describe('EthBlocklistErc20Vault', () => { await snapshotGasCost(tx) }) }) - - describe('ejecting user', () => { - const senderAssets = parseEther('1') - - beforeEach(async () => { - await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) - await vault.connect(admin).setBlocklistManager(blocklistManager.address) - }) - - it('fails for not blocklister', async () => { - await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'AccessDenied' - ) - }) - - it('fails when not harvested', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1.2'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await expect( - vault.connect(blocklistManager).ejectUser(sender.address) - ).to.revertedWithCustomError(vault, 'NotHarvested') - }) - - it('does not fail for user with no vault shares', async () => { - expect(await vault.getShares(other.address)).to.eq(0) - - const tx = await vault.connect(blocklistManager).ejectUser(other.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, other.address, true) - expect(await vault.blockedAccounts(other.address)).to.eq(true) - await snapshotGasCost(tx) - }) - - it('does not fail for user with no osToken shares', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.getShares(sender.address)).to.eq(senderAssets) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - - it('blocklist manager can eject some of the user assets', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const osTokenShares = senderAssets / 2n - const senderShares = await vault.getShares(sender.address) - await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) - - expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(senderShares) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - const ejectedShares = senderShares - (await vault.getShares(sender.address)) - expect(ejectedShares).to.be.lessThan(senderShares) - - const ejectedAssets = await vault.convertToAssets(ejectedShares) - expect(ejectedAssets).to.be.lessThan(senderAssets) - - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) - await snapshotGasCost(tx) - }) - - it('blocklist manager can eject all of the user assets', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - }) }) diff --git a/test/EthBlocklistVault.spec.ts b/test/EthBlocklistVault.spec.ts index 04470156..51e93812 100644 --- a/test/EthBlocklistVault.spec.ts +++ b/test/EthBlocklistVault.spec.ts @@ -1,11 +1,11 @@ import { ethers } from 'hardhat' -import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthBlocklistVault, + IKeeperRewards, Keeper, OsTokenVaultController, - IKeeperRewards, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -165,117 +165,4 @@ describe('EthBlocklistVault', () => { await snapshotGasCost(tx) }) }) - - describe('ejecting user', () => { - const senderAssets = parseEther('1') - - beforeEach(async () => { - await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) - await vault.connect(admin).setBlocklistManager(blocklistManager.address) - }) - - it('fails for not blocklister', async () => { - await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'AccessDenied' - ) - }) - - it('fails when not harvested', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1.2'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await expect( - vault.connect(blocklistManager).ejectUser(sender.address) - ).to.revertedWithCustomError(vault, 'NotHarvested') - }) - - it('does not fail for user with no vault shares', async () => { - expect(await vault.getShares(other.address)).to.eq(0) - - const tx = await vault.connect(blocklistManager).ejectUser(other.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, other.address, true) - expect(await vault.blockedAccounts(other.address)).to.eq(true) - await snapshotGasCost(tx) - }) - - it('does not fail for user with no osToken shares', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.getShares(sender.address)).to.eq(senderAssets) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - - it('blocklist manager can eject some of the user assets', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const osTokenShares = senderAssets / 2n - const senderShares = await vault.getShares(sender.address) - await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) - - expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(senderShares) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - const ejectedShares = senderShares - (await vault.getShares(sender.address)) - expect(ejectedShares).to.be.lessThan(senderShares) - - const ejectedAssets = await vault.convertToAssets(ejectedShares) - expect(ejectedAssets).to.be.lessThan(senderAssets) - - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) - await snapshotGasCost(tx) - }) - - it('blocklist manager can eject all of the user assets', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.blockedAccounts(sender.address)).to.eq(false) - - const tx = await vault.connect(blocklistManager).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'BlocklistUpdated') - .withArgs(blocklistManager.address, sender.address, true) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.blockedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - }) }) diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index b5dd6b98..5ff0eb66 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -1,6 +1,6 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' -import { EthGenesisVault, Keeper, PoolEscrowMock, RewardEthTokenMock } from '../typechain-types' +import { EthGenesisVault, Keeper, PoolEscrowMock, LegacyRewardTokenMock } from '../typechain-types' import { createDepositorMock, ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { expect } from './shared/expect' import keccak256 from 'keccak256' @@ -45,7 +45,7 @@ describe('EthGenesisVault', () => { let admin: Signer, other: Wallet let vault: EthGenesisVault, keeper: Keeper, validatorsRegistry: Contract let poolEscrow: PoolEscrowMock - let rewardEthToken: RewardEthTokenMock + let rewardEthToken: LegacyRewardTokenMock let createGenesisVault: ThenArg>['createEthGenesisVault'] @@ -56,7 +56,13 @@ describe('EthGenesisVault', () => { async function collatEthVault() { if (MAINNET_FORK.enabled) return - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault( + vault, + keeper, + validatorsRegistry, + admin, + await poolEscrow.getAddress() + ) } beforeEach('deploy fixtures', async () => { @@ -215,7 +221,7 @@ describe('EthGenesisVault', () => { }) }) - it('pulls assets on claim exited assets', async () => { + it('pulls withdrawals on claim exited assets', async () => { await acceptPoolEscrowOwnership() await collatEthVault() @@ -260,7 +266,7 @@ describe('EthGenesisVault', () => { await snapshotGasCost(tx) }) - it('pulls assets on single validator registration', async () => { + it('pulls withdrawals on single validator registration', async () => { await acceptPoolEscrowOwnership() await collatEthVault() const validatorDeposit = ethers.parseEther('32') @@ -272,17 +278,17 @@ describe('EthGenesisVault', () => { await setBalance(vaultAddr, 0n) await setBalance(poolEscrowAddr, validatorDeposit + vaultBalance + poolEscrowBalance) expect(await vault.withdrawableAssets()).to.be.greaterThanOrEqual(validatorDeposit) - const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin) + const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin, poolEscrowAddr) await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, validatorDeposit + vaultBalance + poolEscrowBalance) await snapshotGasCost(tx) }) - it('pulls assets on multiple validators registration', async () => { + it('pulls withdrawals on multiple validators registration', async () => { await acceptPoolEscrowOwnership() await collatEthVault() - const validatorsData = await createEthValidatorsData(vault) + const validatorsData = await createEthValidatorsData(vault, await poolEscrow.getAddress()) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(admin).setValidatorsRoot(validatorsData.root) const proof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ diff --git a/test/EthPrivErc20Vault.spec.ts b/test/EthPrivErc20Vault.spec.ts index 6d6af7ec..52f4fcac 100644 --- a/test/EthPrivErc20Vault.spec.ts +++ b/test/EthPrivErc20Vault.spec.ts @@ -1,7 +1,12 @@ import { ethers } from 'hardhat' -import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthPrivErc20Vault, IKeeperRewards, Keeper } from '../typechain-types' +import { + EthPrivErc20Vault, + IKeeperRewards, + Keeper, + OsTokenVaultController, +} from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -17,17 +22,21 @@ describe('EthPrivErc20Vault', () => { const feePercent = 1000 const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' - let sender: Wallet, admin: Signer, other: Wallet, whitelister: Wallet - let vault: EthPrivErc20Vault, keeper: Keeper, validatorsRegistry: Contract + let sender: Wallet, admin: Signer, other: Wallet + let vault: EthPrivErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController let createPrivateVault: ThenArg>['createEthPrivErc20Vault'] beforeEach('deploy fixtures', async () => { - ;[sender, admin, other, whitelister] = await (ethers as any).getSigners() + ;[sender, admin, other] = await (ethers as any).getSigners() ;({ createEthPrivErc20Vault: createPrivateVault, keeper, validatorsRegistry, + osTokenVaultController, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -172,121 +181,30 @@ describe('EthPrivErc20Vault', () => { }) }) - describe('ejecting user', () => { - const senderAssets = parseEther('1') + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint beforeEach(async () => { await vault.connect(admin).updateWhitelist(sender.address, true) await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await vault.connect(sender).deposit(sender.address, referrer, { value: senderAssets }) - await vault.connect(admin).setWhitelister(whitelister.address) - }) - - it('fails for not whitelister', async () => { - await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'AccessDenied' - ) - }) - - it('fails when not harvested', async () => { await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1.2'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await expect(vault.connect(whitelister).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'NotHarvested' - ) + await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) + osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) - it('does not fail for user with no vault shares', async () => { - await vault.connect(whitelister).updateWhitelist(other.address, true) - - expect(await vault.getShares(other.address)).to.eq(0) - expect(await vault.whitelistedAccounts(other.address)).to.eq(true) - - const tx = await vault.connect(whitelister).ejectUser(other.address) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, other.address, false) - expect(await vault.whitelistedAccounts(other.address)).to.eq(false) - await snapshotGasCost(tx) - }) - - it('does not fail for user with no osToken shares', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderAssets) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - - it('whitelister can eject some of the user assets', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const osTokenShares = senderAssets / 2n - const senderShares = await vault.getShares(sender.address) - await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) - - expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderShares) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - const ejectedShares = senderShares - (await vault.getShares(sender.address)) - expect(ejectedShares).to.be.lessThan(senderShares) - - const ejectedAssets = await vault.convertToAssets(ejectedShares) - expect(ejectedAssets).to.be.lessThan(senderAssets) - - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, parseEther('32'), ejectedAssets) - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) - await snapshotGasCost(tx) + it('cannot mint from not whitelisted user', async () => { + await vault.connect(admin).updateWhitelist(sender.address, false) + await expect( + vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + ).to.revertedWithCustomError(vault, 'AccessDenied') }) - it('whitelister can eject all of the user assets', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, 0n, senderAssets) - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(0) + it('can mint from whitelisted user', async () => { + const tx = await vault + .connect(sender) + .mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) + await expect(tx).to.emit(vault, 'OsTokenMinted') await snapshotGasCost(tx) }) }) diff --git a/test/EthPrivVault.spec.ts b/test/EthPrivVault.spec.ts index 605b78d2..746b6c33 100644 --- a/test/EthPrivVault.spec.ts +++ b/test/EthPrivVault.spec.ts @@ -1,28 +1,27 @@ import { ethers } from 'hardhat' -import { Contract, parseEther, Signer, Wallet } from 'ethers' +import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthPrivVault, Keeper, OsTokenVaultController } from '../typechain-types' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' import { ZERO_ADDRESS } from './shared/constants' import snapshotGasCost from './shared/snapshotGasCost' -import { collateralizeEthVault, updateRewards } from './shared/rewards' +import { collateralizeEthVault } from './shared/rewards' import keccak256 from 'keccak256' -import { extractDepositShares, extractExitPositionTicket } from './shared/utils' describe('EthPrivVault', () => { const capacity = ethers.parseEther('1000') const feePercent = 1000 const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' - let sender: Wallet, admin: Signer, other: Wallet, whitelister: Wallet + let sender: Wallet, admin: Signer, other: Wallet let vault: EthPrivVault, keeper: Keeper, validatorsRegistry: Contract, osTokenVaultController: OsTokenVaultController beforeEach('deploy fixtures', async () => { - ;[sender, admin, other, whitelister] = await (ethers as any).getSigners() + ;[sender, admin, other] = await (ethers as any).getSigners() const fixture = await loadFixture(ethVaultFixture) vault = await fixture.createEthPrivVault(admin, { capacity, @@ -77,126 +76,4 @@ describe('EthPrivVault', () => { await snapshotGasCost(tx) }) }) - - describe('ejecting user', () => { - const senderAssets = parseEther('1') - let senderShares: bigint - - beforeEach(async () => { - await vault.connect(admin).updateWhitelist(sender.address, true) - await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await vault.connect(admin).setWhitelister(whitelister.address) - const tx = await vault - .connect(sender) - .deposit(sender.address, referrer, { value: senderAssets }) - senderShares = await extractDepositShares(tx) - }) - - it('fails for not whitelister', async () => { - await expect(vault.connect(other).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'AccessDenied' - ) - }) - - it('fails when not harvested', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - await vault.connect(sender).mintOsToken(sender.address, senderAssets / 2n, ZERO_ADDRESS) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await updateRewards(keeper, [ - { - vault: await vault.getAddress(), - reward: ethers.parseEther('1.2'), - unlockedMevReward: ethers.parseEther('0'), - }, - ]) - await expect(vault.connect(whitelister).ejectUser(sender.address)).to.revertedWithCustomError( - vault, - 'NotHarvested' - ) - }) - - it('does not fail for user with no vault shares', async () => { - await vault.connect(whitelister).updateWhitelist(other.address, true) - - expect(await vault.getShares(other.address)).to.eq(0) - expect(await vault.whitelistedAccounts(other.address)).to.eq(true) - - const tx = await vault.connect(whitelister).ejectUser(other.address) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, other.address, false) - expect(await vault.whitelistedAccounts(other.address)).to.eq(false) - await snapshotGasCost(tx) - }) - - it('does not fail for user with no osToken shares', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderShares) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - const positionTicket = await extractExitPositionTicket(tx) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, positionTicket, senderAssets) - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - - it('whitelister can eject some of the user assets', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) - const osTokenShares = senderAssets / 2n - await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) - - expect(await vault.osTokenPositions(sender.address)).to.eq(osTokenShares) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - expect(await vault.getShares(sender.address)).to.eq(senderShares) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - const ejectedShares = senderShares - (await vault.getShares(sender.address)) - expect(ejectedShares).to.be.lessThan(senderShares) - - const ejectedAssets = await vault.convertToAssets(ejectedShares) - expect(ejectedAssets).to.be.lessThan(senderAssets) - - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx).to.emit(vault, 'ExitQueueEntered') - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(senderShares - ejectedShares) - await snapshotGasCost(tx) - }) - - it('whitelister can eject all of the user assets', async () => { - expect(await vault.osTokenPositions(sender.address)).to.eq(0) - expect(await vault.whitelistedAccounts(sender.address)).to.eq(true) - - const tx = await vault.connect(whitelister).ejectUser(sender.address) - const positionTicket = await extractExitPositionTicket(tx) - await expect(tx) - .to.emit(vault, 'WhitelistUpdated') - .withArgs(whitelister.address, sender.address, false) - await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, positionTicket, senderAssets) - - expect(await vault.whitelistedAccounts(sender.address)).to.eq(false) - expect(await vault.getShares(sender.address)).to.eq(0) - await snapshotGasCost(tx) - }) - }) }) diff --git a/test/EthVault.upgrade.spec.ts b/test/EthVault.upgrade.spec.ts index b65b6ac1..0a8fbfe1 100644 --- a/test/EthVault.upgrade.spec.ts +++ b/test/EthVault.upgrade.spec.ts @@ -15,7 +15,7 @@ import { import snapshotGasCost from './shared/snapshotGasCost' import { deployEthVaultV1, - deployVaultImplementation, + deployEthVaultImplementation, encodeEthErc20VaultInitParams, encodeEthVaultInitParams, ethVaultFixture, @@ -82,7 +82,7 @@ describe('EthVault - upgrade', () => { }) admin = await ethers.getImpersonatedSigner(await vault.admin()) - mockImpl = await deployVaultImplementation( + mockImpl = await deployEthVaultImplementation( 'EthVaultV3Mock', fixture.keeper, fixture.vaultsRegistry, @@ -131,7 +131,7 @@ describe('EthVault - upgrade', () => { }) it('fails for implementation with different vault id', async () => { - const newImpl = await deployVaultImplementation( + const newImpl = await deployEthVaultImplementation( 'EthPrivVaultV3Mock', fixture.keeper, fixture.vaultsRegistry, @@ -150,7 +150,7 @@ describe('EthVault - upgrade', () => { }) it('fails for implementation with too high version', async () => { - const newImpl = await deployVaultImplementation( + const newImpl = await deployEthVaultImplementation( 'EthVaultV4Mock', fixture.keeper, fixture.vaultsRegistry, diff --git a/test/EthVault.withdraw.spec.ts b/test/EthVault.withdraw.spec.ts index 72220a39..61f69229 100644 --- a/test/EthVault.withdraw.spec.ts +++ b/test/EthVault.withdraw.spec.ts @@ -17,7 +17,7 @@ import { deployEthVaultV1, encodeEthVaultInitParams, ethVaultFixture, - upgradeVaultToV2, + upgradeVault, } from './shared/fixtures' import { expect } from './shared/expect' import { @@ -108,7 +108,7 @@ describe('EthVault - withdraw', () => { positionTicketV1 = await extractExitPositionTicket(tx) timestampV1 = await getBlockTimestamp(tx) - await upgradeVaultToV2(vaultV1, vaultImpl) + await upgradeVault(vaultV1, vaultImpl) vault = EthVault__factory.connect(await vaultV1.getAddress(), admin) expect(await vault.version()).to.be.eq(2) diff --git a/test/VaultsRegistry.spec.ts b/test/VaultsRegistry.spec.ts index 1bbc529f..7cb92792 100644 --- a/test/VaultsRegistry.spec.ts +++ b/test/VaultsRegistry.spec.ts @@ -3,7 +3,7 @@ import { Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { EthVaultFactory, VaultsRegistry } from '../typechain-types' import { - deployVaultImplementation, + deployEthVaultImplementation, encodeEthVaultInitParams, ethVaultFixture, } from './shared/fixtures' @@ -31,7 +31,7 @@ describe('VaultsRegistry', () => { ethVaultFactory = fixture.ethVaultFactory vaultsRegistry = fixture.vaultsRegistry - newVaultImpl = await deployVaultImplementation( + newVaultImpl = await deployEthVaultImplementation( 'EthVaultV3Mock', fixture.keeper, fixture.vaultsRegistry, diff --git a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap index fc3b7b90..8ef2fe63 100644 --- a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71171, + "gasUsed": 71149, } `; @@ -14,34 +14,6 @@ Object { } `; -exports[`EthBlocklistErc20Vault ejecting user blocklist manager can eject all of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 120550, -} -`; - -exports[`EthBlocklistErc20Vault ejecting user blocklist manager can eject some of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 146827, -} -`; - -exports[`EthBlocklistErc20Vault ejecting user does not fail for user with no osToken shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 120550, -} -`; - -exports[`EthBlocklistErc20Vault ejecting user does not fail for user with no vault shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 56104, -} -`; - exports[`EthBlocklistErc20Vault mint osToken can mint from not blocked user 1`] = ` Object { "calldataByteLength": 100, diff --git a/test/__snapshots__/EthBlocklistVault.spec.ts.snap b/test/__snapshots__/EthBlocklistVault.spec.ts.snap index 2de3c991..f422fa1e 100644 --- a/test/__snapshots__/EthBlocklistVault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistVault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69078, + "gasUsed": 69056, } `; @@ -14,34 +14,6 @@ Object { } `; -exports[`EthBlocklistVault ejecting user blocklist manager can eject all of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 118535, -} -`; - -exports[`EthBlocklistVault ejecting user blocklist manager can eject some of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 144812, -} -`; - -exports[`EthBlocklistVault ejecting user does not fail for user with no osToken shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 118535, -} -`; - -exports[`EthBlocklistVault ejecting user does not fail for user with no vault shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 55884, -} -`; - exports[`EthBlocklistVault mint osToken can mint from not blocked user 1`] = ` Object { "calldataByteLength": 100, diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 9c50c27a..a56daeb8 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,42 +10,42 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79638, + "gasUsed": 79660, } `; -exports[`EthGenesisVault pulls assets on claim exited assets 1`] = ` +exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77231, + "gasUsed": 77303, } `; -exports[`EthGenesisVault pulls assets on multiple validators registration 1`] = ` +exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638183, + "gasUsed": 638285, } `; -exports[`EthGenesisVault pulls assets on single validator registration 1`] = ` +exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301781, + "gasUsed": 301879, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150242, + "gasUsed": 150264, } `; exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 145811, + "gasUsed": 145833, } `; @@ -59,6 +59,6 @@ Object { exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167342, + "gasUsed": 167364, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index 62cd2081..c0ec74f3 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71159, + "gasUsed": 71137, } `; @@ -14,31 +14,10 @@ Object { } `; -exports[`EthPrivErc20Vault ejecting user does not fail for user with no osToken shares 1`] = ` +exports[`EthPrivErc20Vault mint osToken can mint from whitelisted user 1`] = ` Object { - "calldataByteLength": 36, - "gasUsed": 98634, -} -`; - -exports[`EthPrivErc20Vault ejecting user does not fail for user with no vault shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 34188, -} -`; - -exports[`EthPrivErc20Vault ejecting user whitelister can eject all of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 98634, -} -`; - -exports[`EthPrivErc20Vault ejecting user whitelister can eject some of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 124911, + "calldataByteLength": 100, + "gasUsed": 174096, } `; diff --git a/test/__snapshots__/EthPrivVault.spec.ts.snap b/test/__snapshots__/EthPrivVault.spec.ts.snap index 0dde2ac6..ebdedaf3 100644 --- a/test/__snapshots__/EthPrivVault.spec.ts.snap +++ b/test/__snapshots__/EthPrivVault.spec.ts.snap @@ -1,33 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`EthPrivVault ejecting user does not fail for user with no osToken shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 96619, -} -`; - -exports[`EthPrivVault ejecting user does not fail for user with no vault shares 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 33968, -} -`; - -exports[`EthPrivVault ejecting user whitelister can eject all of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 96619, -} -`; - -exports[`EthPrivVault ejecting user whitelister can eject some of the user assets 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 122896, -} -`; - exports[`EthPrivVault mint osToken can mint from not whitelisted user 1`] = ` Object { "calldataByteLength": 100, diff --git a/test/__snapshots__/EthVault.deposit.spec.ts.snap b/test/__snapshots__/EthVault.deposit.spec.ts.snap index f9585fe0..6858829e 100644 --- a/test/__snapshots__/EthVault.deposit.spec.ts.snap +++ b/test/__snapshots__/EthVault.deposit.spec.ts.snap @@ -24,6 +24,6 @@ Object { exports[`EthVault - deposit full vault: assets & shares update state and deposit 1`] = ` Object { "calldataByteLength": 260, - "gasUsed": 155354, + "gasUsed": 155321, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index 1f325696..85d4dd42 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168286, + "gasUsed": 168253, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 109839, + "gasUsed": 109869, } `; diff --git a/test/__snapshots__/EthVault.state.spec.ts.snap b/test/__snapshots__/EthVault.state.spec.ts.snap index aaf93a87..ee528fe1 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthVault - state allocates fee to recipient when delta is above zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117586, + "gasUsed": 117553, } `; exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117672, + "gasUsed": 117639, } `; exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 107225, + "gasUsed": 107192, } `; diff --git a/test/__snapshots__/EthVault.whitelist.spec.ts.snap b/test/__snapshots__/EthVault.whitelist.spec.ts.snap index 694e10bd..0fff6a6c 100644 --- a/test/__snapshots__/EthVault.whitelist.spec.ts.snap +++ b/test/__snapshots__/EthVault.whitelist.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthVault - whitelist deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69066, + "gasUsed": 69044, } `; @@ -17,7 +17,7 @@ Object { exports[`EthVault - whitelist set whitelister admin can update whitelister 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 36245, + "gasUsed": 36223, } `; diff --git a/test/__snapshots__/KeeperRewards.spec.ts.snap b/test/__snapshots__/KeeperRewards.spec.ts.snap index 0351ad61..84165ae3 100644 --- a/test/__snapshots__/KeeperRewards.spec.ts.snap +++ b/test/__snapshots__/KeeperRewards.spec.ts.snap @@ -3,42 +3,42 @@ exports[`KeeperRewards harvest (own escrow) succeeds for latest rewards root 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 111407, + "gasUsed": 111374, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 113561, + "gasUsed": 113528, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 74328, + "gasUsed": 74295, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for latest rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 143961, + "gasUsed": 143928, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 146115, + "gasUsed": 146082, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 90495, + "gasUsed": 90462, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index 3652711d..cd131463 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -31,6 +31,6 @@ Object { exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170719, + "gasUsed": 170686, } `; diff --git a/test/shared/contracts.ts b/test/shared/contracts.ts index 1718dc1e..77d2f7c3 100644 --- a/test/shared/contracts.ts +++ b/test/shared/contracts.ts @@ -7,7 +7,7 @@ import EthPrivErc20VaultV1 from './artifacts/EthPrivErc20Vault.json' import EthPrivVaultV1 from './artifacts/EthPrivVault.json' import EthGenesisVaultV1 from './artifacts/EthGenesisVault.json' -export async function getValidatorsRegistryFactory(): Promise { +export async function getEthValidatorsRegistryFactory(): Promise { return await ethers.getContractFactory(EthValidatorsRegistry.abi, EthValidatorsRegistry.bytecode) } diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index d543b21a..8de3f899 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -33,6 +33,8 @@ import { IKeeperRewards, Keeper, Keeper__factory, + LegacyRewardTokenMock, + LegacyRewardTokenMock__factory, OsToken, OsToken__factory, OsTokenConfig, @@ -43,8 +45,6 @@ import { PoolEscrowMock__factory, PriceFeed, PriceFeed__factory, - RewardEthTokenMock, - RewardEthTokenMock__factory, RewardSplitterFactory, RewardSplitterFactory__factory, SharedMevEscrow, @@ -52,7 +52,7 @@ import { VaultsRegistry, VaultsRegistry__factory, } from '../../typechain-types' -import { getValidatorsRegistryFactory } from './contracts' +import { getEthValidatorsRegistryFactory } from './contracts' import { EXITING_ASSETS_MIN_DELAY, MAX_AVG_REWARD_PER_SECOND, @@ -72,7 +72,7 @@ import { SECURITY_DEPOSIT, VALIDATORS_MIN_ORACLES, } from './constants' -import { EthErc20VaultInitParamsStruct, EthVaultInitParamsStruct, VaultType } from './types' +import { EthErc20VaultInitParamsStruct, EthVaultInitParamsStruct, EthVaultType } from './types' import { DepositorMock } from '../../typechain-types/contracts/mocks/DepositorMock' import { DepositorMock__factory } from '../../typechain-types/factories/contracts/mocks/DepositorMock__factory' import { UnknownVaultMock } from '../../typechain-types/contracts/mocks/UnknownVaultMock' @@ -107,10 +107,10 @@ export const transferOwnership = async function ( await contract.connect(newOwner).acceptOwnership() } -export const upgradeVaultToV2 = async function ( - vault: VaultType, +export const upgradeVault = async function ( + vault: EthVaultType, implementation: string -): Promise { +): Promise { const adminAddr = await vault.admin() const admin = await ethers.getImpersonatedSigner(adminAddr) await setBalance(adminAddr, ethers.parseEther('1')) @@ -120,7 +120,7 @@ export const upgradeVaultToV2 = async function ( export const updateVaultState = async function ( keeper: Keeper, - vault: VaultType, + vault: EthVaultType, harvestParams: IKeeperRewards.HarvestParamsStruct ) { if (!(await keeper.canHarvest(await vault.getAddress()))) { @@ -129,7 +129,7 @@ export const updateVaultState = async function ( await vault.updateState(harvestParams) } -export const createDepositorMock = async function (vault: VaultType): Promise { +export const createDepositorMock = async function (vault: EthVaultType): Promise { const depositorMockFactory = await ethers.getContractFactory('DepositorMock') const contract = await depositorMockFactory.deploy(await vault.getAddress()) return DepositorMock__factory.connect( @@ -157,8 +157,8 @@ export const createMulticallMock = async function (): Promise { await ethers.provider.getSigner() ) } -export const createValidatorsRegistry = async function (): Promise { - const validatorsRegistryFactory = await getValidatorsRegistryFactory() +export const createEthValidatorsRegistry = async function (): Promise { + const validatorsRegistryFactory = await getEthValidatorsRegistryFactory() const signer = await ethers.provider.getSigner() if (MAINNET_FORK.enabled) { @@ -201,7 +201,7 @@ export const createVaultsRegistry = async function (): Promise { return registry } -export const createSharedMevEscrow = async function ( +export const createEthSharedMevEscrow = async function ( vaultsRegistry: VaultsRegistry ): Promise { const signer = await ethers.provider.getSigner() @@ -392,7 +392,7 @@ export const createEthVaultFactory = async function ( ) } -export const deployGenesisVaultImpl = async function ( +export const deployEthGenesisVaultImpl = async function ( keeper: Keeper, vaultsRegistry: VaultsRegistry, validatorsRegistry: Contract, @@ -400,7 +400,7 @@ export const deployGenesisVaultImpl = async function ( osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, poolEscrow: PoolEscrowMock, - rewardEthToken: RewardEthTokenMock + rewardEthToken: LegacyRewardTokenMock ): Promise { const factory = await ethers.getContractFactory('EthGenesisVault') const constructorArgs = [ @@ -420,7 +420,7 @@ export const deployGenesisVaultImpl = async function ( return vaultImpl } -export const deployVaultImplementation = async function ( +export const deployEthVaultImplementation = async function ( vaultType: string, keeper: Keeper, vaultsRegistry: VaultsRegistry, @@ -542,7 +542,6 @@ interface EthVaultFixture { sharedMevEscrow: SharedMevEscrow validatorsRegistry: Contract ethVaultFactory: EthVaultFactory - ethVaultMockFactory: EthVaultFactory ethPrivVaultFactory: EthVaultFactory ethErc20VaultFactory: EthVaultFactory ethPrivErc20VaultFactory: EthVaultFactory @@ -602,15 +601,15 @@ interface EthVaultFixture { admin: Signer, vaultParams: EthVaultInitParamsStruct, skipFork?: boolean - ): Promise<[EthGenesisVault, RewardEthTokenMock, PoolEscrowMock]> + ): Promise<[EthGenesisVault, LegacyRewardTokenMock, PoolEscrowMock]> } export const ethVaultFixture = async function (): Promise { const dao = await (ethers as any).provider.getSigner() const vaultsRegistry = await createVaultsRegistry() - const validatorsRegistry = await createValidatorsRegistry() + const validatorsRegistry = await createEthValidatorsRegistry() - const sharedMevEscrow = await createSharedMevEscrow(vaultsRegistry) + const sharedMevEscrow = await createEthSharedMevEscrow(vaultsRegistry) // 1. calc osToken address const _osTokenAddress = ethers.getCreateAddress({ @@ -686,7 +685,7 @@ export const ethVaultFixture = async function (): Promise { 'EthBlocklistErc20Vault', 'EthVaultMock', ]) { - const vaultImpl = await deployVaultImplementation( + const vaultImpl = await deployEthVaultImplementation( vaultType, keeper, vaultsRegistry, @@ -714,7 +713,6 @@ export const ethVaultFixture = async function (): Promise { const ethPrivErc20VaultFactory = factories['EthPrivErc20Vault'] const ethBlocklistVaultFactory = factories['EthBlocklistVault'] const ethBlocklistErc20VaultFactory = factories['EthBlocklistErc20Vault'] - const ethVaultMockFactory = factories['EthVaultMock'] return { vaultsRegistry, @@ -725,7 +723,6 @@ export const ethVaultFixture = async function (): Promise { ethPrivVaultFactory, ethErc20VaultFactory, ethPrivErc20VaultFactory, - ethVaultMockFactory, ethBlocklistVaultFactory, ethBlocklistErc20VaultFactory, osTokenVaultController, @@ -752,7 +749,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethVaultSharedMevEscrow } const vault = EthVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) - await upgradeVaultToV2(vault, implementations['EthVault']) + await upgradeVault(vault, implementations['EthVault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -809,7 +806,7 @@ export const ethVaultFixture = async function (): Promise { vaultParams: EthVaultInitParamsStruct, isOwnMevEscrow = false ): Promise => { - const tx = await ethVaultMockFactory + const tx = await factories['EthVaultMock'] .connect(admin) .createVault(encodeEthVaultInitParams(vaultParams), isOwnMevEscrow, { value: SECURITY_DEPOSIT, @@ -837,7 +834,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethPrivVaultSharedMevEscrow } const vault = EthPrivVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) - await upgradeVaultToV2(vault, implementations['EthPrivVault']) + await upgradeVault(vault, implementations['EthPrivVault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -876,7 +873,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethErc20VaultSharedMevEscrow } const vault = EthErc20Vault__factory.connect(vaultAddress, await ethers.provider.getSigner()) - await upgradeVaultToV2(vault, implementations['EthErc20Vault']) + await upgradeVault(vault, implementations['EthErc20Vault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -904,7 +901,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress, await ethers.provider.getSigner() ) - await upgradeVaultToV2(vault, implementations['EthPrivErc20Vault']) + await upgradeVault(vault, implementations['EthPrivErc20Vault']) await setBalance(await vault.admin(), parseEther('1000')) return vault }, @@ -928,25 +925,26 @@ export const ethVaultFixture = async function (): Promise { admin: Signer, vaultParams: EthVaultInitParamsStruct, skipFork: boolean = false - ): Promise<[EthGenesisVault, RewardEthTokenMock, PoolEscrowMock]> => { - let poolEscrow: PoolEscrowMock, rewardEthToken: RewardEthTokenMock + ): Promise<[EthGenesisVault, LegacyRewardTokenMock, PoolEscrowMock]> => { + let poolEscrow: PoolEscrowMock, rewardEthToken: LegacyRewardTokenMock if (!MAINNET_FORK.enabled || skipFork) { poolEscrow = await createPoolEscrow(dao.address, skipFork) - const rewardEthTokenMockFactory = await ethers.getContractFactory('RewardEthTokenMock') - const rewardEthTokenMock = await rewardEthTokenMockFactory.deploy() - rewardEthToken = RewardEthTokenMock__factory.connect( - await rewardEthTokenMock.getAddress(), + const legacyRewardTokenMockFactory = + await ethers.getContractFactory('LegacyRewardTokenMock') + const legacyRewardTokenMock = await legacyRewardTokenMockFactory.deploy() + rewardEthToken = LegacyRewardTokenMock__factory.connect( + await legacyRewardTokenMock.getAddress(), dao ) } else { poolEscrow = PoolEscrowMock__factory.connect(NETWORKS.mainnet.genesisVault.poolEscrow, dao) - rewardEthToken = RewardEthTokenMock__factory.connect( + rewardEthToken = LegacyRewardTokenMock__factory.connect( NETWORKS.mainnet.genesisVault.rewardEthToken, dao ) } - const vaultImpl = await deployGenesisVaultImpl( + const vaultImpl = await deployEthGenesisVaultImpl( keeper, vaultsRegistry, validatorsRegistry, @@ -983,7 +981,7 @@ export const ethVaultFixture = async function (): Promise { mainnetDeployment.EthGenesisVault, await ethers.provider.getSigner() ) - await upgradeVaultToV2(vault, vaultImpl) + await upgradeVault(vault, vaultImpl) await updateVaultState( keeper, vault, diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index 0d35ddbe..c78302b0 100644 --- a/test/shared/rewards.ts +++ b/test/shared/rewards.ts @@ -22,7 +22,7 @@ import { } from './utils' import { getOraclesSignatures } from './fixtures' import { MAINNET_FORK } from '../../helpers/constants' -import { VaultType } from './types' +import { EthVaultType } from './types' export type RewardsTree = StandardMerkleTree<[string, bigint, bigint]> @@ -180,10 +180,11 @@ export async function collateralizeEthV1Vault( } export async function collateralizeEthVault( - vault: VaultType, + vault: EthVaultType, keeper: Keeper, validatorsRegistry: Contract, - admin: Signer + admin: Signer, + genesisVaultPoolEscrow: string | null = null ) { const vaultAddress = await vault.getAddress() const balanceBefore = await ethers.provider.getBalance(vaultAddress) @@ -195,7 +196,7 @@ export async function collateralizeEthVault( .connect(admin) .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) const receivedShares = await extractDepositShares(tx) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, validatorsRegistry, admin, genesisVaultPoolEscrow) // exit validator const response = await vault.connect(admin).enterExitQueue(receivedShares, adminAddr) diff --git a/test/shared/types.ts b/test/shared/types.ts index f557a72f..40483a21 100644 --- a/test/shared/types.ts +++ b/test/shared/types.ts @@ -21,7 +21,7 @@ export type EthErc20VaultInitParamsStruct = { metadataIpfsHash: string } -export type VaultType = +export type EthVaultType = | EthVault | EthPrivVault | EthErc20Vault diff --git a/test/shared/validators.ts b/test/shared/validators.ts index 7870a6c2..2719d8b0 100644 --- a/test/shared/validators.ts +++ b/test/shared/validators.ts @@ -13,7 +13,7 @@ import { VALIDATORS_MIN_ORACLES, } from './constants' import { getOraclesSignatures } from './fixtures' -import { VaultType } from './types' +import { EthVaultType } from './types' export const secretKeys = [ '0x2c66340f2d886f3fc4cfef10a802ddbaf4a37ffb49533b604f8a50804e8d198f', @@ -144,11 +144,10 @@ export function getWithdrawalCredentials(vaultAddress: string): Buffer { export async function createValidators( depositAmount: bigint, - vaultAddress: string + withdrawalCredentials: Buffer ): Promise { await bls.init(bls.BLS12_381) - const withdrawalCredentials = getWithdrawalCredentials(vaultAddress) const validators: Buffer[] = [] for (let i = 0; i < secretKeys.length; i++) { const secretKey = new bls.SecretKey() @@ -188,9 +187,15 @@ export function appendDepositData( return Buffer.concat([validator, DepositData.hashTreeRoot(depositData)]) } -export async function createEthValidatorsData(vault: VaultType): Promise { +export async function createEthValidatorsData( + vault: EthVaultType, + genesisVaultPoolEscrow: string | null = null +): Promise { const validatorDeposit = ethers.parseEther('32') - const validators = await createValidators(validatorDeposit, await vault.getAddress()) + const withdrawalCredentials = getWithdrawalCredentials( + genesisVaultPoolEscrow !== null ? genesisVaultPoolEscrow : await vault.getAddress() + ) + const validators = await createValidators(validatorDeposit, withdrawalCredentials) const tree = StandardMerkleTree.of( validators.map((v, i) => [v, i]), ['bytes', 'uint256'] @@ -209,7 +214,7 @@ export async function getEthValidatorsSigningData( deadline: bigint, exitSignaturesIpfsHash: string, keeper: Keeper, - vault: VaultType, + vault: EthVaultType, validatorsRegistryRoot: BytesLike ) { return { @@ -277,12 +282,13 @@ export function getValidatorsMultiProof( } export async function registerEthValidator( - vault: VaultType, + vault: EthVaultType, keeper: Keeper, validatorsRegistry: Contract, - admin: Signer + admin: Signer, + genesisVaultPoolEscrow: string | null = null ): Promise { - const validatorsData = await createEthValidatorsData(vault) + const validatorsData = await createEthValidatorsData(vault, genesisVaultPoolEscrow) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(admin).setValidatorsRoot(validatorsData.root) const validator = validatorsData.validators[0] From 99a8074d62d922047f9790ebf648a2bef0403726 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 5 Mar 2024 13:06:42 +0200 Subject: [PATCH 05/29] Update snapshots --- test/__snapshots__/EthFoxVault.spec.ts.snap | 4 ++-- test/__snapshots__/EthGenesisVault.spec.ts.snap | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index edc68163..8c6e43a0 100644 --- a/test/__snapshots__/EthFoxVault.spec.ts.snap +++ b/test/__snapshots__/EthFoxVault.spec.ts.snap @@ -31,14 +31,14 @@ Object { exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for collateralized vault 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 118081, + "gasUsed": 119385, } `; exports[`EthFoxVault ejecting user does not fail for user with no vault shares 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 55786, + "gasUsed": 55791, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index a56daeb8..8e1df947 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,42 +10,42 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79660, + "gasUsed": 79638, } `; exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77303, + "gasUsed": 77231, } `; exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638285, + "gasUsed": 638213, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301879, + "gasUsed": 301807, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150264, + "gasUsed": 150242, } `; exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 145833, + "gasUsed": 145811, } `; @@ -59,6 +59,6 @@ Object { exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167364, + "gasUsed": 167342, } `; From 3731bada70376ad39f216c89c96c0192c574c386 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 6 Mar 2024 10:25:53 +0200 Subject: [PATCH 06/29] Fix linting --- contracts/vaults/ethereum/custom/EthFoxVault.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/vaults/ethereum/custom/EthFoxVault.sol b/contracts/vaults/ethereum/custom/EthFoxVault.sol index 99d524a8..6023e038 100644 --- a/contracts/vaults/ethereum/custom/EthFoxVault.sol +++ b/contracts/vaults/ethereum/custom/EthFoxVault.sol @@ -105,7 +105,7 @@ contract EthFoxVault is // send user shares to exit queue _enterExitQueue(user, userShares, user); - emit UserEjected(user, userShares); + emit UserEjected(user, userShares); } /** From 4be225b6a2b8c80504ab2b8a6ef9f93bfae1b1df Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 6 Mar 2024 10:39:59 +0200 Subject: [PATCH 07/29] Move queued shares in interface --- contracts/interfaces/IVaultState.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/interfaces/IVaultState.sol b/contracts/interfaces/IVaultState.sol index 45815baf..e82b1681 100644 --- a/contracts/interfaces/IVaultState.sol +++ b/contracts/interfaces/IVaultState.sol @@ -26,12 +26,6 @@ interface IVaultState is IVaultFee { */ event FeeSharesMinted(address receiver, uint256 shares, uint256 assets); - /** - * @notice Queued Shares - * @return The total number of shares queued for exit - */ - function queuedShares() external view returns (uint128); - /** * @notice Total assets in the Vault * @return The total amount of the underlying asset that is "managed" by Vault @@ -56,6 +50,12 @@ interface IVaultState is IVaultFee { */ function withdrawableAssets() external view returns (uint256); + /** + * @notice Queued Shares + * @return The total number of shares queued for exit + */ + function queuedShares() external view returns (uint128); + /** * @notice Total Exiting Assets * @return The total number of assets queued for exit From 2e0946d6abe502c003dfaf3dfacfb08e872e15c5 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 6 Mar 2024 13:13:16 +0200 Subject: [PATCH 08/29] Emit Transfer event on update exit queue --- contracts/vaults/ethereum/EthErc20Vault.sol | 10 +++++ .../vaults/ethereum/EthPrivErc20Vault.sol | 20 ++++----- contracts/vaults/modules/VaultEnterExit.sol | 5 ++- contracts/vaults/modules/VaultOsToken.sol | 43 +++++++------------ contracts/vaults/modules/VaultState.sol | 30 +++++++------ contracts/vaults/modules/VaultToken.sol | 6 +++ contracts/vaults/modules/VaultWhitelist.sol | 2 +- test/EthGenesisVault.spec.ts | 1 + .../EthBlocklistErc20Vault.spec.ts.snap | 6 +-- test/__snapshots__/EthErc20Vault.spec.ts.snap | 6 +-- .../EthGenesisVault.spec.ts.snap | 4 +- .../EthPrivErc20Vault.spec.ts.snap | 6 +-- .../EthVault.multicall.spec.ts.snap | 4 +- .../__snapshots__/EthVault.state.spec.ts.snap | 4 +- .../__snapshots__/EthVault.token.spec.ts.snap | 8 ++-- .../EthVault.withdraw.spec.ts.snap | 2 +- .../EthVaultFactory.spec.ts.snap | 8 ++-- .../__snapshots__/RewardSplitter.spec.ts.snap | 4 +- .../SharedMevEscrow.spec.ts.snap | 2 +- 19 files changed, 90 insertions(+), 81 deletions(-) diff --git a/contracts/vaults/ethereum/EthErc20Vault.sol b/contracts/vaults/ethereum/EthErc20Vault.sol index c4efd9c3..52a1a02f 100644 --- a/contracts/vaults/ethereum/EthErc20Vault.sol +++ b/contracts/vaults/ethereum/EthErc20Vault.sol @@ -134,6 +134,16 @@ contract EthErc20Vault is return _version; } + /// @inheritdoc VaultState + function _updateExitQueue() + internal + virtual + override(VaultState, VaultToken) + returns (uint256 burnedShares) + { + return super._updateExitQueue(); + } + /// @inheritdoc VaultState function _mintShares( address owner, diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index 5867fef3..847409fd 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -73,6 +73,16 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth __VaultWhitelist_init(_admin); } + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { + return keccak256('EthPrivErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { + return _version; + } + /// @inheritdoc IVaultEthStaking function deposit( address receiver, @@ -101,16 +111,6 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth return super.mintOsToken(receiver, osTokenShares, referrer); } - /// @inheritdoc IVaultVersion - function vaultId() public pure virtual override(IVaultVersion, EthErc20Vault) returns (bytes32) { - return keccak256('EthPrivErc20Vault'); - } - - /// @inheritdoc IVaultVersion - function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { - return _version; - } - /// @inheritdoc ERC20Upgradeable function _transfer(address from, address to, uint256 amount) internal virtual override { _checkWhitelist(from); diff --git a/contracts/vaults/modules/VaultEnterExit.sol b/contracts/vaults/modules/VaultEnterExit.sol index 7dbdcdc7..4cdcd8cc 100644 --- a/contracts/vaults/modules/VaultEnterExit.sol +++ b/contracts/vaults/modules/VaultEnterExit.sol @@ -140,7 +140,10 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, if (totalExitedTickets <= positionTicket) return (0, 0); // calculate exited tickets and assets - exitedTickets = Math.min(exitingTickets, totalExitedTickets - positionTicket); + unchecked { + // cannot underflow as totalExitedTickets > positionTicket + exitedTickets = Math.min(exitingTickets, totalExitedTickets - positionTicket); + } return (exitedTickets, _convertExitTicketsToAssets(exitedTickets)); } diff --git a/contracts/vaults/modules/VaultOsToken.sol b/contracts/vaults/modules/VaultOsToken.sol index 827fb073..55fea244 100644 --- a/contracts/vaults/modules/VaultOsToken.sol +++ b/contracts/vaults/modules/VaultOsToken.sol @@ -44,7 +44,7 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I } /// @inheritdoc IVaultOsToken - function osTokenPositions(address user) public view override returns (uint128 shares) { + function osTokenPositions(address user) external view override returns (uint128 shares) { OsTokenPosition memory position = _positions[user]; if (position.shares != 0) _syncPositionFee(position); return position.shares; @@ -272,40 +272,27 @@ abstract contract VaultOsToken is VaultImmutables, VaultState, VaultEnterExit, I } /** - * @dev Internal function for retrieving the amount of locked shares for a given user. - * Reverts if the vault is not harvested. + * @notice Internal function for checking position validity. Reverts if it is invalid. * @param user The address of the user - * @return The amount of locked shares */ - function _getLockedShares(address user) internal view returns (uint256) { - uint256 osTokenShares = osTokenPositions(user); - if (osTokenShares == 0) return 0; - - // calculate locked assets - uint256 lockedAssets = Math.mulDiv( - _osTokenVaultController.convertToAssets(osTokenShares), - _maxPercent, - _osTokenConfig.ltvPercent() - ); - if (lockedAssets == 0) return 0; + function _checkOsTokenPosition(address user) internal view { + // fetch user position + OsTokenPosition memory position = _positions[user]; + if (position.shares == 0) return; // check whether vault assets are up to date _checkHarvested(); - // convert to vault shares - return convertToShares(lockedAssets); - } - - /** - * @notice Internal function for checking position validity - * @param user The address of the user - */ - function _checkOsTokenPosition(address user) internal view { - uint256 lockedShares = _getLockedShares(user); - if (lockedShares == 0) return; + // sync fee + _syncPositionFee(position); - // validate position LTV - if (lockedShares > _balances[user]) revert Errors.LowLtv(); + // calculate and validate position LTV + if ( + Math.mulDiv(convertToAssets(_balances[user]), _osTokenConfig.ltvPercent(), _maxPercent) < + _osTokenVaultController.convertToAssets(position.shares) + ) { + revert Errors.LowLtv(); + } } /** diff --git a/contracts/vaults/modules/VaultState.sol b/contracts/vaults/modules/VaultState.sol index f4c44db1..8fc26f0d 100644 --- a/contracts/vaults/modules/VaultState.sol +++ b/contracts/vaults/modules/VaultState.sol @@ -23,6 +23,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint128 internal _totalShares; uint128 internal _totalAssets; + /// @inheritdoc IVaultState uint128 public override queuedShares; uint128 internal _unclaimedAssets; @@ -32,6 +33,7 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint256 private _capacity; + /// @inheritdoc IVaultState uint128 public override totalExitingAssets; uint128 internal _totalExitingTickets; uint256 internal _totalExitedTickets; @@ -118,27 +120,27 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault // SLOAD to memory uint256 _totalExitingAssets = totalExitingAssets; - // apply penalty to exiting assets - uint256 exitingAssetsPenalty = Math.mulDiv( - penalty, - _totalExitingAssets, - _totalExitingAssets + newTotalAssets - ); + if (_totalExitingAssets > 0) { + // apply penalty to exiting assets + uint256 exitingAssetsPenalty = Math.mulDiv( + penalty, + _totalExitingAssets, + _totalExitingAssets + newTotalAssets + ); - unchecked { - // cannot underflow as exitingAssetsPenalty <= penalty - penalty -= exitingAssetsPenalty; + // apply penalty to total exiting assets + unchecked { + // cannot underflow as exitingAssetsPenalty <= penalty + penalty -= exitingAssetsPenalty; + // cannot underflow as exitingAssetsPenalty <= _totalExitingAssets + totalExitingAssets = SafeCast.toUint128(_totalExitingAssets - exitingAssetsPenalty); + } } // subtract penalty from total assets (excludes exiting assets) if (penalty > 0) { _totalAssets = SafeCast.toUint128(newTotalAssets - penalty); } - - // subtract penalty from total exiting assets - if (exitingAssetsPenalty > 0) { - totalExitingAssets = SafeCast.toUint128(_totalExitingAssets - exitingAssetsPenalty); - } return; } diff --git a/contracts/vaults/modules/VaultToken.sol b/contracts/vaults/modules/VaultToken.sol index 7e95f666..03ae52fe 100644 --- a/contracts/vaults/modules/VaultToken.sol +++ b/contracts/vaults/modules/VaultToken.sol @@ -37,6 +37,12 @@ abstract contract VaultToken is Initializable, ERC20Upgradeable, VaultState, IVa emit Transfer(owner, address(0), shares); } + /// @inheritdoc VaultState + function _updateExitQueue() internal virtual override returns (uint256 burnedShares) { + burnedShares = super._updateExitQueue(); + if (burnedShares != 0) emit Transfer(address(this), address(0), burnedShares); + } + /// @inheritdoc ERC20Upgradeable function _transfer(address from, address to, uint256 amount) internal virtual override { if (from == address(0) || to == address(0)) revert Errors.ZeroAddress(); diff --git a/contracts/vaults/modules/VaultWhitelist.sol b/contracts/vaults/modules/VaultWhitelist.sol index 83aef0b8..54554680 100644 --- a/contracts/vaults/modules/VaultWhitelist.sol +++ b/contracts/vaults/modules/VaultWhitelist.sol @@ -20,7 +20,7 @@ abstract contract VaultWhitelist is Initializable, VaultAdmin, IVaultWhitelist { mapping(address => bool) public override whitelistedAccounts; /// @inheritdoc IVaultWhitelist - function updateWhitelist(address account, bool approved) public override { + function updateWhitelist(address account, bool approved) external override { if (msg.sender != whitelister) revert Errors.AccessDenied(); if (whitelistedAccounts[account] == approved) return; whitelistedAccounts[account] = approved; diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 5ff0eb66..f5287b51 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -398,6 +398,7 @@ describe('EthGenesisVault', () => { }) it('skips updating legacy with zero total assets', async () => { + if (MAINNET_FORK.enabled) return await acceptPoolEscrowOwnership() await rewardEthToken.setTotalStaked(0n) await rewardEthToken.setTotalRewards(0n) diff --git a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap index 8ef2fe63..1180d9c3 100644 --- a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -3,14 +3,14 @@ exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71149, + "gasUsed": 71181, } `; exports[`EthBlocklistErc20Vault deposit deposit through receive fallback can be called by not blocked sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 78315, + "gasUsed": 78347, } `; @@ -24,6 +24,6 @@ Object { exports[`EthBlocklistErc20Vault transfer can transfer 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 59012, + "gasUsed": 58987, } `; diff --git a/test/__snapshots__/EthErc20Vault.spec.ts.snap b/test/__snapshots__/EthErc20Vault.spec.ts.snap index ad24c40c..96d0553e 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthErc20Vault deposit emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68826, + "gasUsed": 68858, } `; exports[`EthErc20Vault deposit through receive fallback function emits transfer event 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 76084, + "gasUsed": 76116, } `; exports[`EthErc20Vault enter exit queue emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 96055, + "gasUsed": 96030, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 8e1df947..a4c8c982 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -17,7 +17,7 @@ Object { exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77231, + "gasUsed": 77206, } `; @@ -52,7 +52,7 @@ Object { exports[`EthGenesisVault update state splits penalty between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 119951, + "gasUsed": 119650, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index c0ec74f3..d005196a 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,14 +3,14 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71137, + "gasUsed": 71169, } `; exports[`EthPrivErc20Vault deposit deposit through receive fallback can be called by whitelisted sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 78318, + "gasUsed": 78350, } `; @@ -24,6 +24,6 @@ Object { exports[`EthPrivErc20Vault transfer can transfer to whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 59040, + "gasUsed": 59015, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index 85d4dd42..7780e669 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168253, + "gasUsed": 168196, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 109869, + "gasUsed": 109844, } `; diff --git a/test/__snapshots__/EthVault.state.spec.ts.snap b/test/__snapshots__/EthVault.state.spec.ts.snap index ee528fe1..6f1db2a9 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -10,14 +10,14 @@ Object { exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117639, + "gasUsed": 117338, } `; exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 107192, + "gasUsed": 107117, } `; diff --git a/test/__snapshots__/EthVault.token.spec.ts.snap b/test/__snapshots__/EthVault.token.spec.ts.snap index a0a89440..29a129bd 100644 --- a/test/__snapshots__/EthVault.token.spec.ts.snap +++ b/test/__snapshots__/EthVault.token.spec.ts.snap @@ -24,27 +24,27 @@ Object { exports[`EthVault - token transfer from when the spender has enough allowance when the token owner has enough balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 54827, + "gasUsed": 54802, } `; exports[`EthVault - token transfer from when the spender has unlimited allowance does not decrease the spender allowance 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 61303, + "gasUsed": 61278, } `; exports[`EthVault - token transfer when the sender transfers all balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 54490, + "gasUsed": 54465, } `; exports[`EthVault - token transfer when the sender transfers zero tokens transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 36566, + "gasUsed": 36541, } `; diff --git a/test/__snapshots__/EthVault.withdraw.spec.ts.snap b/test/__snapshots__/EthVault.withdraw.spec.ts.snap index 2e446e0e..4201d357 100644 --- a/test/__snapshots__/EthVault.withdraw.spec.ts.snap +++ b/test/__snapshots__/EthVault.withdraw.spec.ts.snap @@ -31,7 +31,7 @@ Object { exports[`EthVault - withdraw enter exit queue locks assets for the time of exit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 77184, + "gasUsed": 77127, } `; diff --git a/test/__snapshots__/EthVaultFactory.spec.ts.snap b/test/__snapshots__/EthVaultFactory.spec.ts.snap index f0a7f936..406947fa 100644 --- a/test/__snapshots__/EthVaultFactory.spec.ts.snap +++ b/test/__snapshots__/EthVaultFactory.spec.ts.snap @@ -3,28 +3,28 @@ exports[`EthVaultFactory EthErc20Vault private vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 577167, + "gasUsed": 577199, } `; exports[`EthVaultFactory EthErc20Vault private vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 428348, + "gasUsed": 428380, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 553235, + "gasUsed": 553267, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 404416, + "gasUsed": 404448, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index cd131463..8e606aaa 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -24,13 +24,13 @@ Object { exports[`RewardSplitter withdraw rewards can claim vault tokens for ERC-20 vault 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78205, + "gasUsed": 78180, } `; exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170686, + "gasUsed": 170629, } `; diff --git a/test/__snapshots__/SharedMevEscrow.spec.ts.snap b/test/__snapshots__/SharedMevEscrow.spec.ts.snap index d26d366c..99c6db1e 100644 --- a/test/__snapshots__/SharedMevEscrow.spec.ts.snap +++ b/test/__snapshots__/SharedMevEscrow.spec.ts.snap @@ -3,6 +3,6 @@ exports[`SharedMevEscrow vault deployment gas 1`] = ` Object { "calldataByteLength": 683, - "gasUsed": 167457, + "gasUsed": 167433, } `; From 9fdce3f2fa5499aa046b4f75d96dbdff30a18337 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 6 Mar 2024 14:28:16 +0200 Subject: [PATCH 09/29] Disable slither shadow state variable warning --- contracts/vaults/ethereum/EthBlocklistErc20Vault.sol | 1 + contracts/vaults/ethereum/EthBlocklistVault.sol | 1 + contracts/vaults/ethereum/EthGenesisVault.sol | 1 + contracts/vaults/ethereum/EthPrivErc20Vault.sol | 1 + contracts/vaults/ethereum/EthPrivVault.sol | 1 + 5 files changed, 5 insertions(+) diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol index 798181a5..9d505f76 100644 --- a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -23,6 +23,7 @@ contract EthBlocklistErc20Vault is VaultBlocklist, IEthBlocklistErc20Vault { + // slither-disable-next-line shadowing-state uint8 private constant _version = 2; /** diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol index 12385209..a1c84758 100644 --- a/contracts/vaults/ethereum/EthBlocklistVault.sol +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -17,6 +17,7 @@ import {EthVault, IEthVault} from './EthVault.sol'; * @notice Defines the Ethereum staking Vault with blocking addresses functionality */ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlocklistVault { + // slither-disable-next-line shadowing-state uint8 private constant _version = 2; /** diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index 67ac1676..2407d36a 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -23,6 +23,7 @@ import {EthVault, IEthVault} from './EthVault.sol'; * @notice Defines the Genesis Vault for Ethereum staking migrated from StakeWise v2 */ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { + // slither-disable-next-line shadowing-state uint8 private constant _version = 2; /// @custom:oz-upgrades-unsafe-allow state-variable-immutable diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index 847409fd..2577c287 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -18,6 +18,7 @@ import {EthErc20Vault, IEthErc20Vault} from './EthErc20Vault.sol'; * @notice Defines the Ethereum staking Vault with whitelist and ERC-20 token */ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEthPrivErc20Vault { + // slither-disable-next-line shadowing-state uint8 private constant _version = 2; /** diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index fbfa5938..ecf315df 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -17,6 +17,7 @@ import {EthVault, IEthVault} from './EthVault.sol'; * @notice Defines the Ethereum staking Vault with whitelist */ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault { + // slither-disable-next-line shadowing-state uint8 private constant _version = 2; /** From 1a6c8b2b41801502bbe503ef2f7f5667a33886c6 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Thu, 7 Mar 2024 20:20:14 +0200 Subject: [PATCH 10/29] Rename ExitQueueEntered to V2ExitQueueEntered --- abi/IEthBlocklistErc20Vault.json | 39 ++++++++++++++++++- abi/IEthBlocklistVault.json | 39 ++++++++++++++++++- abi/IEthErc20Vault.json | 39 ++++++++++++++++++- abi/IEthFoxVault.json | 39 ++++++++++++++++++- abi/IEthGenesisVault.json | 39 ++++++++++++++++++- abi/IEthPrivErc20Vault.json | 39 ++++++++++++++++++- abi/IEthPrivVault.json | 39 ++++++++++++++++++- abi/IEthVault.json | 39 ++++++++++++++++++- abi/IVaultEnterExit.json | 39 ++++++++++++++++++- abi/IVaultEthStaking.json | 39 ++++++++++++++++++- abi/IVaultOsToken.json | 39 ++++++++++++++++++- abi/IVaultToken.json | 39 ++++++++++++++++++- contracts/interfaces/IVaultEnterExit.sol | 19 ++++++++- contracts/vaults/modules/VaultEnterExit.sol | 2 +- helpers/constants.ts | 4 +- test/EthErc20Vault.spec.ts | 4 +- test/EthFoxVault.spec.ts | 6 +-- test/EthVault.multicall.spec.ts | 2 +- test/EthVault.withdraw.spec.ts | 16 ++++---- test/__snapshots__/EthErc20Vault.spec.ts.snap | 2 +- test/__snapshots__/EthFoxVault.spec.ts.snap | 2 +- .../EthVault.multicall.spec.ts.snap | 2 +- .../EthVault.withdraw.spec.ts.snap | 2 +- .../__snapshots__/RewardSplitter.spec.ts.snap | 2 +- .../SharedMevEscrow.spec.ts.snap | 2 +- test/shared/constants.ts | 2 +- 26 files changed, 497 insertions(+), 38 deletions(-) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index 7fd9f593..072c01e1 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -148,7 +148,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -472,6 +472,43 @@ "name": "Transfer", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index bba88550..3c0d4df8 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -123,7 +123,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -422,6 +422,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index a6b58147..aa1ff233 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -428,6 +428,43 @@ "name": "Transfer", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index 24f53cc9..dad4d020 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -160,7 +160,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -330,6 +330,43 @@ "name": "UserEjected", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index 1f019294..441f361b 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -434,6 +434,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 00c4270b..8c40441f 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -428,6 +428,43 @@ "name": "Transfer", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index 96a01dcc..eba6fdc6 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -378,6 +378,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IEthVault.json b/abi/IEthVault.json index 70f49211..de74fcaa 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -378,6 +378,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IVaultEnterExit.json b/abi/IVaultEnterExit.json index 40e975a1..d513a237 100644 --- a/abi/IVaultEnterExit.json +++ b/abi/IVaultEnterExit.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -211,6 +211,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "inputs": [], "name": "admin", diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index 3dee0cda..76ae7f82 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -230,6 +230,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/abi/IVaultOsToken.json b/abi/IVaultOsToken.json index 657628a4..c0f42b08 100644 --- a/abi/IVaultOsToken.json +++ b/abi/IVaultOsToken.json @@ -79,7 +79,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -359,6 +359,43 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "inputs": [], "name": "admin", diff --git a/abi/IVaultToken.json b/abi/IVaultToken.json index 6cabfd64..a3e6bb4e 100644 --- a/abi/IVaultToken.json +++ b/abi/IVaultToken.json @@ -104,7 +104,7 @@ { "indexed": false, "internalType": "uint256", - "name": "assets", + "name": "shares", "type": "uint256" } ], @@ -261,6 +261,43 @@ "name": "Transfer", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "positionTicket", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "V2ExitQueueEntered", + "type": "event" + }, { "inputs": [], "name": "DOMAIN_SEPARATOR", diff --git a/contracts/interfaces/IVaultEnterExit.sol b/contracts/interfaces/IVaultEnterExit.sol index f12db10a..8eff2cba 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -36,16 +36,31 @@ interface IVaultEnterExit is IVaultState { event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); /** - * @notice Event emitted on shares added to the exit queue + * @notice Event emitted on shares added to the V1 exit queue * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position - * @param assets The number of assets that queued for the exit + * @param shares The number of shares that queued for the exit */ event ExitQueueEntered( address indexed owner, address indexed receiver, uint256 positionTicket, + uint256 shares + ); + + /** + * @notice Event emitted on shares added to the V2 exit queue + * @param owner The address that owns the shares + * @param receiver The address that will receive withdrawn assets + * @param positionTicket The exit queue ticket that was assigned to the position + * @param assets The number of assets that queued for the exit + */ + event V2ExitQueueEntered( + address indexed owner, + address indexed receiver, + uint256 positionTicket, + uint256 shares, uint256 assets ); diff --git a/contracts/vaults/modules/VaultEnterExit.sol b/contracts/vaults/modules/VaultEnterExit.sol index 4cdcd8cc..df3a0aa5 100644 --- a/contracts/vaults/modules/VaultEnterExit.sol +++ b/contracts/vaults/modules/VaultEnterExit.sol @@ -224,7 +224,7 @@ abstract contract VaultEnterExit is VaultImmutables, Initializable, VaultState, keccak256(abi.encode(receiver, block.timestamp, positionTicket)) ] = exitingTickets; - emit ExitQueueEntered(user, receiver, positionTicket, assets); + emit V2ExitQueueEntered(user, receiver, positionTicket, shares, assets); } /** diff --git a/helpers/constants.ts b/helpers/constants.ts index 08d55aca..cdce38c5 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -14,7 +14,7 @@ export const NETWORKS: { governor: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', validatorsRegistry: '0x4242424242424242424242424242424242424242', securityDeposit: 1000000000n, // 1 gwei - exitedAssetsClaimDelay: 30 * 60 * 60, // 30 hours + exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours // Keeper oracles: [ @@ -76,7 +76,7 @@ export const NETWORKS: { governor: '0x144a98cb1CdBb23610501fE6108858D9B7D24934', validatorsRegistry: '0x00000000219ab540356cBB839Cbe05303d7705Fa', securityDeposit: 1000000000n, // 1 gwei - exitedAssetsClaimDelay: 30 * 60 * 60, // 30 hours + exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours // Keeper oracles: [ diff --git a/test/EthErc20Vault.spec.ts b/test/EthErc20Vault.spec.ts index 5526bd3d..441667d4 100644 --- a/test/EthErc20Vault.spec.ts +++ b/test/EthErc20Vault.spec.ts @@ -135,8 +135,8 @@ describe('EthErc20Vault', () => { const receipt = await vault.connect(sender).enterExitQueue(shares, receiver.address) const positionTicket = await extractExitPositionTicket(receipt) await expect(receipt) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, receiver.address, positionTicket, amount) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(sender.address, receiver.address, positionTicket, shares, amount) await expect(receipt).to.emit(vault, 'Transfer').withArgs(sender.address, ZERO_ADDRESS, shares) expect(await vault.totalExitingAssets()).to.be.eq(totalExitingBefore + amount) expect(await vault.totalAssets()).to.be.eq(totalAssetsBefore) diff --git a/test/EthFoxVault.spec.ts b/test/EthFoxVault.spec.ts index 3e42e168..f1649753 100644 --- a/test/EthFoxVault.spec.ts +++ b/test/EthFoxVault.spec.ts @@ -215,7 +215,7 @@ describe('EthFoxVault', () => { .to.emit(vault, 'BlocklistUpdated') .withArgs(blocklistManager.address, other.address, true) expect(await vault.blockedAccounts(other.address)).to.eq(true) - await expect(tx).to.not.emit(vault, 'ExitQueueEntered') + await expect(tx).to.not.emit(vault, 'V2ExitQueueEntered') await snapshotGasCost(tx) }) @@ -229,8 +229,8 @@ describe('EthFoxVault', () => { .withArgs(blocklistManager.address, sender.address, true) expect(await vault.blockedAccounts(sender.address)).to.eq(true) await expect(tx) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(sender.address, sender.address, positionTicket, senderShares) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(sender.address, sender.address, positionTicket, senderAssets, senderShares) await expect(tx).to.emit(vault, 'UserEjected').withArgs(sender.address, senderShares) expect(await vault.getShares(sender.address)).to.eq(0) await snapshotGasCost(tx) diff --git a/test/EthVault.multicall.spec.ts b/test/EthVault.multicall.spec.ts index 3575b35c..b3853acc 100644 --- a/test/EthVault.multicall.spec.ts +++ b/test/EthVault.multicall.spec.ts @@ -117,7 +117,7 @@ describe('EthVault - multicall', () => { const timestamp = await getBlockTimestamp(receipt) await expect(receipt).to.emit(keeper, 'Harvested') await expect(receipt).to.emit(mevEscrow, 'Harvested') - await expect(receipt).to.emit(vault, 'ExitQueueEntered') + await expect(receipt).to.emit(vault, 'V2ExitQueueEntered') await snapshotGasCost(receipt) // wait for exit queue to complete and withdraw exited assets diff --git a/test/EthVault.withdraw.spec.ts b/test/EthVault.withdraw.spec.ts index 61f69229..ed1e1b9a 100644 --- a/test/EthVault.withdraw.spec.ts +++ b/test/EthVault.withdraw.spec.ts @@ -211,8 +211,8 @@ describe('EthVault - withdraw', () => { const positionTicket = await extractExitPositionTicket(receipt) const timestamp = await getBlockTimestamp(receipt) await expect(receipt) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(holder.address, receiver.address, positionTicket, holderAssets) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(holder.address, receiver.address, positionTicket, holderShares, holderAssets) expect(await vault.totalAssets()).to.be.eq(totalAssetsBefore - holderAssets) expect(await vault.totalShares()).to.be.eq(totalSharesBefore - holderShares) @@ -1149,8 +1149,8 @@ describe('EthVault - withdraw', () => { alicePositionTicket = await extractExitPositionTicket(response) aliceTimestamp = await getBlockTimestamp(response) await expect(response) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(alice.address, alice.address, alicePositionTicket, 1821) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(alice.address, alice.address, alicePositionTicket, 1000, 1821) aliceShares -= 1000n totalShares -= 1000n @@ -1168,8 +1168,8 @@ describe('EthVault - withdraw', () => { bobTimestamp = await getBlockTimestamp(response) await expect(response) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(bob.address, bob.address, bobPositionTicket, 8000) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(bob.address, bob.address, bobPositionTicket, 4393, 8000) aliceAssets += 1n // rounding error bobShares -= 4393n @@ -1234,8 +1234,8 @@ describe('EthVault - withdraw', () => { alicePositionTicket = await extractExitPositionTicket(response) aliceTimestamp = await getBlockTimestamp(response) await expect(response) - .to.emit(vault, 'ExitQueueEntered') - .withArgs(alice.address, alice.address, latestPositionTicket, 6824n) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(alice.address, alice.address, latestPositionTicket, 1001, 6824) expect(alicePositionTicket).to.be.eq(latestPositionTicket) aliceShares -= 1001n diff --git a/test/__snapshots__/EthErc20Vault.spec.ts.snap b/test/__snapshots__/EthErc20Vault.spec.ts.snap index 96d0553e..e4386f4c 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -17,7 +17,7 @@ Object { exports[`EthErc20Vault enter exit queue emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 96030, + "gasUsed": 96285, } `; diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index 8c6e43a0..a4d88765 100644 --- a/test/__snapshots__/EthFoxVault.spec.ts.snap +++ b/test/__snapshots__/EthFoxVault.spec.ts.snap @@ -31,7 +31,7 @@ Object { exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for collateralized vault 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 119385, + "gasUsed": 119659, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index 7780e669..cd9430e5 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168196, + "gasUsed": 168451, } `; diff --git a/test/__snapshots__/EthVault.withdraw.spec.ts.snap b/test/__snapshots__/EthVault.withdraw.spec.ts.snap index 4201d357..9f11d9f4 100644 --- a/test/__snapshots__/EthVault.withdraw.spec.ts.snap +++ b/test/__snapshots__/EthVault.withdraw.spec.ts.snap @@ -31,7 +31,7 @@ Object { exports[`EthVault - withdraw enter exit queue locks assets for the time of exit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 77127, + "gasUsed": 77382, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index 8e606aaa..f2cc9f02 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -31,6 +31,6 @@ Object { exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170629, + "gasUsed": 170884, } `; diff --git a/test/__snapshots__/SharedMevEscrow.spec.ts.snap b/test/__snapshots__/SharedMevEscrow.spec.ts.snap index 99c6db1e..d26d366c 100644 --- a/test/__snapshots__/SharedMevEscrow.spec.ts.snap +++ b/test/__snapshots__/SharedMevEscrow.spec.ts.snap @@ -3,6 +3,6 @@ exports[`SharedMevEscrow vault deployment gas 1`] = ` Object { "calldataByteLength": 683, - "gasUsed": 167433, + "gasUsed": 167457, } `; diff --git a/test/shared/constants.ts b/test/shared/constants.ts index 557160b8..98bef6ca 100644 --- a/test/shared/constants.ts +++ b/test/shared/constants.ts @@ -34,7 +34,7 @@ export const ORACLES = [ export const REWARDS_MIN_ORACLES = 6 export const VALIDATORS_MIN_ORACLES = 6 export const ORACLES_CONFIG = 'QmbwQ6zFEWs1SjLPGk4NNJqn4wduVe6dK3xyte2iG59Uru' -export const EXITING_ASSETS_MIN_DELAY = 30 * 60 * 60 // 30 hours +export const EXITING_ASSETS_MIN_DELAY = 24 * 60 * 60 // 24 hours export const OSTOKEN_FEE = 500 // 5% export const OSTOKEN_CAPACITY = ethers.parseEther('10000000') export const OSTOKEN_NAME = 'Staked ETH' From 27384dfd6481e828c7b41faab938f0f21c7876f6 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Fri, 8 Mar 2024 15:01:35 +0200 Subject: [PATCH 11/29] Revert changing withdrawal creds to pool escrow for genesis vault --- contracts/vaults/ethereum/EthGenesisVault.sol | 5 ----- contracts/vaults/modules/VaultValidators.sol | 2 +- test/EthGenesisVault.spec.ts | 4 ++-- test/__snapshots__/EthGenesisVault.spec.ts.snap | 4 ++-- test/shared/rewards.ts | 5 ++--- test/shared/validators.ts | 5 ++--- 6 files changed, 9 insertions(+), 16 deletions(-) diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index 2407d36a..4ea47010 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -254,11 +254,6 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { if (escrowBalance != 0) _poolEscrow.withdraw(payable(this), escrowBalance); } - /// @inheritdoc VaultValidators - function _withdrawalCredentials() internal view override returns (bytes memory) { - return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(_poolEscrow)); - } - /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/contracts/vaults/modules/VaultValidators.sol b/contracts/vaults/modules/VaultValidators.sol index 2899cbc2..8a54a73a 100644 --- a/contracts/vaults/modules/VaultValidators.sol +++ b/contracts/vaults/modules/VaultValidators.sol @@ -157,7 +157,7 @@ abstract contract VaultValidators is * @dev Internal function for calculating Vault withdrawal credentials * @return The credentials used for the validators withdrawals */ - function _withdrawalCredentials() internal view virtual returns (bytes memory) { + function _withdrawalCredentials() internal view returns (bytes memory) { return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)); } diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index f5287b51..4ee10c43 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -278,7 +278,7 @@ describe('EthGenesisVault', () => { await setBalance(vaultAddr, 0n) await setBalance(poolEscrowAddr, validatorDeposit + vaultBalance + poolEscrowBalance) expect(await vault.withdrawableAssets()).to.be.greaterThanOrEqual(validatorDeposit) - const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin, poolEscrowAddr) + const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin) await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, validatorDeposit + vaultBalance + poolEscrowBalance) @@ -288,7 +288,7 @@ describe('EthGenesisVault', () => { it('pulls withdrawals on multiple validators registration', async () => { await acceptPoolEscrowOwnership() await collatEthVault() - const validatorsData = await createEthValidatorsData(vault, await poolEscrow.getAddress()) + const validatorsData = await createEthValidatorsData(vault) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(admin).setValidatorsRoot(validatorsData.root) const proof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index a4c8c982..51309ab0 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -24,14 +24,14 @@ Object { exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638213, + "gasUsed": 638183, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301807, + "gasUsed": 301781, } `; diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index c78302b0..404de1ae 100644 --- a/test/shared/rewards.ts +++ b/test/shared/rewards.ts @@ -183,8 +183,7 @@ export async function collateralizeEthVault( vault: EthVaultType, keeper: Keeper, validatorsRegistry: Contract, - admin: Signer, - genesisVaultPoolEscrow: string | null = null + admin: Signer ) { const vaultAddress = await vault.getAddress() const balanceBefore = await ethers.provider.getBalance(vaultAddress) @@ -196,7 +195,7 @@ export async function collateralizeEthVault( .connect(admin) .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) const receivedShares = await extractDepositShares(tx) - await registerEthValidator(vault, keeper, validatorsRegistry, admin, genesisVaultPoolEscrow) + await registerEthValidator(vault, keeper, validatorsRegistry, admin) // exit validator const response = await vault.connect(admin).enterExitQueue(receivedShares, adminAddr) diff --git a/test/shared/validators.ts b/test/shared/validators.ts index 2719d8b0..0bc9aa99 100644 --- a/test/shared/validators.ts +++ b/test/shared/validators.ts @@ -285,10 +285,9 @@ export async function registerEthValidator( vault: EthVaultType, keeper: Keeper, validatorsRegistry: Contract, - admin: Signer, - genesisVaultPoolEscrow: string | null = null + admin: Signer ): Promise { - const validatorsData = await createEthValidatorsData(vault, genesisVaultPoolEscrow) + const validatorsData = await createEthValidatorsData(vault) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(admin).setValidatorsRoot(validatorsData.root) const validator = validatorsData.validators[0] From 95a493e2ab633cf1bc98a2d90318c833b6d07530 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sun, 10 Mar 2024 16:13:13 +0200 Subject: [PATCH 12/29] Deploy new factories, implementations to holesky --- .openzeppelin/unknown-17000.json | 3614 +++++++++++++++++ contracts/vaults/ethereum/EthPrivVault.sol | 2 +- deployments/goerli.json | 14 - deployments/holesky.json | 12 +- helpers/constants.ts | 6 +- helpers/types.ts | 4 +- package.json | 3 +- tasks/eth-full-deploy-local.ts | 31 +- tasks/eth-full-deploy.ts | 22 +- .../EthGenesisVault.spec.ts.snap | 14 +- 10 files changed, 3676 insertions(+), 46 deletions(-) delete mode 100644 deployments/goerli.json diff --git a/.openzeppelin/unknown-17000.json b/.openzeppelin/unknown-17000.json index e2c0a324..e5935e8d 100644 --- a/.openzeppelin/unknown-17000.json +++ b/.openzeppelin/unknown-17000.json @@ -2495,6 +2495,3620 @@ "0x23c85111045b3db22aEe822DAA3C09b7fBAFa437", "0x16c35CC583b35c301D1884D4cdFb6e06A2dF45f2" ] + }, + "77717de6b32ad8c67e88ba0599c10e0659dac72224d95fcb42f204fe871ce012": { + "address": "0x468FD65EfA48650F660456a71DC5be32D27D0B46", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "154", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "160", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "208", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "209", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "210", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "211", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "261", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "311", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "312", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "362", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "363", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "413", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "463", + "type": "t_array(t_uint256)50_storage", + "contract": "EthVault", + "src": "contracts/vaults/ethereum/EthVault.sol:144" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "b4d6592cd0d47ab68f86eed01f77cabd7bc0fc7d2271838cdcec81d064d1cf29": { + "address": "0x3Be1c4315AbE43D0EA1D45567f6c0f3f1faa989e", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "154", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "160", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "208", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "209", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "210", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "211", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "261", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "311", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "312", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "362", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "363", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "413", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "463", + "type": "t_array(t_uint256)50_storage", + "contract": "EthVault", + "src": "contracts/vaults/ethereum/EthVault.sol:144" + }, + { + "label": "whitelister", + "offset": 0, + "slot": "513", + "type": "t_address", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:17" + }, + { + "label": "whitelistedAccounts", + "offset": 0, + "slot": "514", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "515", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "565", + "type": "t_array(t_uint256)50_storage", + "contract": "EthPrivVault", + "src": "contracts/vaults/ethereum/EthPrivVault.sol:119" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "437cb9ecdfd78db225e2f264dbeea2b27185401f2ec0ed661581ab8437f42b04": { + "address": "0x1367B8196ab30E89f95a1F55a241bf880EA632c1", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "154", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "160", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "208", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "209", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "210", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "211", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "261", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "311", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "312", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "362", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "363", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "413", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "463", + "type": "t_array(t_uint256)50_storage", + "contract": "EthVault", + "src": "contracts/vaults/ethereum/EthVault.sol:144" + }, + { + "label": "blocklistManager", + "offset": 0, + "slot": "513", + "type": "t_address", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:17" + }, + { + "label": "blockedAccounts", + "offset": 0, + "slot": "514", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "515", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "565", + "type": "t_array(t_uint256)50_storage", + "contract": "EthBlocklistVault", + "src": "contracts/vaults/ethereum/EthBlocklistVault.sol:115" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "da1495f16b575210110671160464407c4ba5905e45ab26adef49ca7b1b67a0a0": { + "address": "0xD9564d35b17d212D6c06842f28882730a4D91Df3", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "name", + "offset": 0, + "slot": "0", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:21" + }, + { + "label": "symbol", + "offset": 0, + "slot": "1", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:24" + }, + { + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:30" + }, + { + "label": "nonces", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:33" + }, + { + "label": "_initialDomainSeparator", + "offset": 0, + "slot": "4", + "type": "t_bytes32", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:173" + }, + { + "label": "admin", + "offset": 0, + "slot": "55", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "106", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "156", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "156", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "157", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "209", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "210", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "211", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "212", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "214", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "215", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "263", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "264", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "265", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "266", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "316", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "366", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "367", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "417", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "418", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "468", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultToken", + "src": "contracts/vaults/modules/VaultToken.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "518", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "568", + "type": "t_array(t_uint256)50_storage", + "contract": "EthErc20Vault", + "src": "contracts/vaults/ethereum/EthErc20Vault.sol:196" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "63a6de4f9b821a8421b40705638b681f424815e2e41d224b84e895b910301cc1": { + "address": "0x5b817621EBE00622b9a71b53c942b392751c8197", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "name", + "offset": 0, + "slot": "0", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:21" + }, + { + "label": "symbol", + "offset": 0, + "slot": "1", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:24" + }, + { + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:30" + }, + { + "label": "nonces", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:33" + }, + { + "label": "_initialDomainSeparator", + "offset": 0, + "slot": "4", + "type": "t_bytes32", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:173" + }, + { + "label": "admin", + "offset": 0, + "slot": "55", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "106", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "156", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "156", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "157", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "209", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "210", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "211", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "212", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "214", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "215", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "263", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "264", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "265", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "266", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "316", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "366", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "367", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "417", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "418", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "468", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultToken", + "src": "contracts/vaults/modules/VaultToken.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "518", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "568", + "type": "t_array(t_uint256)50_storage", + "contract": "EthErc20Vault", + "src": "contracts/vaults/ethereum/EthErc20Vault.sol:196" + }, + { + "label": "whitelister", + "offset": 0, + "slot": "618", + "type": "t_address", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:17" + }, + { + "label": "whitelistedAccounts", + "offset": 0, + "slot": "619", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "620", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "670", + "type": "t_array(t_uint256)50_storage", + "contract": "EthPrivErc20Vault", + "src": "contracts/vaults/ethereum/EthPrivErc20Vault.sol:127" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "18bc8e3d805f7bd154337f15824fef967f941d03257dd6e97ebba22f037aa8cd": { + "address": "0x3BEc3c1cf81A1176c12550B4315bdd53A2B4Fd5D", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "name", + "offset": 0, + "slot": "0", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:21" + }, + { + "label": "symbol", + "offset": 0, + "slot": "1", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:24" + }, + { + "label": "allowance", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:30" + }, + { + "label": "nonces", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:33" + }, + { + "label": "_initialDomainSeparator", + "offset": 0, + "slot": "4", + "type": "t_bytes32", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC20Upgradeable", + "src": "contracts/base/ERC20Upgradeable.sol:173" + }, + { + "label": "admin", + "offset": 0, + "slot": "55", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "106", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "156", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "156", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "157", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "207", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "208", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "209", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "210", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "211", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "212", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "213", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "214", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "215", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "263", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "264", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "265", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "266", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "316", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "366", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "367", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "417", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "418", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "468", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultToken", + "src": "contracts/vaults/modules/VaultToken.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "518", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "568", + "type": "t_array(t_uint256)50_storage", + "contract": "EthErc20Vault", + "src": "contracts/vaults/ethereum/EthErc20Vault.sol:196" + }, + { + "label": "blocklistManager", + "offset": 0, + "slot": "618", + "type": "t_address", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:17" + }, + { + "label": "blockedAccounts", + "offset": 0, + "slot": "619", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "620", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "670", + "type": "t_array(t_uint256)50_storage", + "contract": "EthBlocklistErc20Vault", + "src": "contracts/vaults/ethereum/EthBlocklistErc20Vault.sol:128" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "e79c52c02f6efd8231a7c92236d33188a70199efc986c25cfa6924c32e35ceb4": { + "address": "0x0C2eC14603Ad9c14a820ad0C91122210Ab84A9e5", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "154", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "160", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "208", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "209", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "210", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "211", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "261", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_positions", + "offset": 0, + "slot": "311", + "type": "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:31" + }, + { + "label": "__gap", + "offset": 0, + "slot": "312", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultOsToken", + "src": "contracts/vaults/modules/VaultOsToken.sol:303" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "362", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "363", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "413", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "__gap", + "offset": 0, + "slot": "463", + "type": "t_array(t_uint256)50_storage", + "contract": "EthVault", + "src": "contracts/vaults/ethereum/EthVault.sol:144" + }, + { + "label": "__gap", + "offset": 0, + "slot": "513", + "type": "t_array(t_uint256)50_storage", + "contract": "EthGenesisVault", + "src": "contracts/vaults/ethereum/EthGenesisVault.sol:262" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(OsTokenPosition)10746_storage)": { + "label": "mapping(address => struct IVaultOsToken.OsTokenPosition)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OsTokenPosition)10746_storage": { + "label": "struct IVaultOsToken.OsTokenPosition", + "members": [ + { + "label": "shares", + "type": "t_uint128", + "offset": 0, + "slot": "0" + }, + { + "label": "cumulativeFeePerShare", + "type": "t_uint128", + "offset": 16, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "81179c73530b8cbd7ca438fd5fb7cc9d024b887ac318fb87f204a5a12fe597ee": { + "address": "0x60CE7c5547Ada69042Df8aC4f40B74ED0031E90d", + "layout": { + "solcVersion": "0.8.22", + "storage": [ + { + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:16" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultAdmin", + "src": "contracts/vaults/modules/VaultAdmin.sol:49" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultVersion", + "src": "contracts/vaults/modules/VaultVersion.sol:66" + }, + { + "label": "feeRecipient", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:21" + }, + { + "label": "feePercent", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultFee", + "src": "contracts/vaults/modules/VaultFee.sol:62" + }, + { + "label": "_totalShares", + "offset": 0, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:23" + }, + { + "label": "_totalAssets", + "offset": 16, + "slot": "152", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:24" + }, + { + "label": "queuedShares", + "offset": 0, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:27" + }, + { + "label": "_unclaimedAssets", + "offset": 16, + "slot": "153", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:28" + }, + { + "label": "_exitQueue", + "offset": 0, + "slot": "154", + "type": "t_struct(History)12476_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:30" + }, + { + "label": "_exitRequests", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_address,t_uint256)", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:32" + }, + { + "label": "_capacity", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:34" + }, + { + "label": "totalExitingAssets", + "offset": 0, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:37" + }, + { + "label": "_totalExitingTickets", + "offset": 16, + "slot": "158", + "type": "t_uint128", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:38" + }, + { + "label": "_totalExitedTickets", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "160", + "type": "t_array(t_uint256)48_storage", + "contract": "VaultState", + "src": "contracts/vaults/modules/VaultState.sol:330" + }, + { + "label": "validatorsRoot", + "offset": 0, + "slot": "208", + "type": "t_bytes32", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:29" + }, + { + "label": "validatorIndex", + "offset": 0, + "slot": "209", + "type": "t_uint256", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:32" + }, + { + "label": "_keysManager", + "offset": 0, + "slot": "210", + "type": "t_address", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:34" + }, + { + "label": "__gap", + "offset": 0, + "slot": "211", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultValidators", + "src": "contracts/vaults/modules/VaultValidators.sol:199" + }, + { + "label": "__gap", + "offset": 0, + "slot": "261", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEnterExit", + "src": "contracts/vaults/modules/VaultEnterExit.sol:265" + }, + { + "label": "_ownMevEscrow", + "offset": 0, + "slot": "311", + "type": "t_address", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "312", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultMev", + "src": "contracts/vaults/modules/VaultMev.sol:77" + }, + { + "label": "__gap", + "offset": 0, + "slot": "362", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultEthStaking", + "src": "contracts/vaults/modules/VaultEthStaking.sol:153" + }, + { + "label": "blocklistManager", + "offset": 0, + "slot": "412", + "type": "t_address", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:17" + }, + { + "label": "blockedAccounts", + "offset": 0, + "slot": "413", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "414", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "464", + "type": "t_array(t_uint256)50_storage", + "contract": "EthFoxVault", + "src": "contracts/vaults/ethereum/custom/EthFoxVault.sol:157" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)105_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(ReentrancyGuardStorage)229_storage": { + "label": "struct ReentrancyGuardUpgradeable.ReentrancyGuardStorage", + "members": [ + { + "label": "_status", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(Checkpoint)12470_storage)dyn_storage": { + "label": "struct ExitQueue.Checkpoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Checkpoint)12470_storage": { + "label": "struct ExitQueue.Checkpoint", + "members": [ + { + "label": "totalTickets", + "type": "t_uint160", + "offset": 0, + "slot": "0" + }, + { + "label": "exitedAssets", + "type": "t_uint96", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(History)12476_storage": { + "label": "struct ExitQueue.History", + "members": [ + { + "label": "checkpoints", + "type": "t_array(t_struct(Checkpoint)12470_storage)dyn_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint160": { + "label": "uint160", + "numberOfBytes": "20" + }, + "t_uint96": { + "label": "uint96", + "numberOfBytes": "12" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ReentrancyGuard": [ + { + "contract": "ReentrancyGuardUpgradeable", + "label": "_status", + "type": "t_uint256", + "src": "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol:40", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } } } } diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index ecf315df..1652a4fd 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -8,7 +8,7 @@ import {IEthVaultFactory} from '../../interfaces/IEthVaultFactory.sol'; import {VaultEthStaking, IVaultEthStaking} from '../modules/VaultEthStaking.sol'; import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; import {VaultWhitelist} from '../modules/VaultWhitelist.sol'; -import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {IVaultVersion} from '../modules/VaultVersion.sol'; import {EthVault, IEthVault} from './EthVault.sol'; /** diff --git a/deployments/goerli.json b/deployments/goerli.json deleted file mode 100644 index 69cd7948..00000000 --- a/deployments/goerli.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "VaultsRegistry": "0xA7b1A1469b6eCAF941E0Bb8d5BB50C572072Ec20", - "Keeper": "0x893ceb1cF23475defE3747670EbE4b40e629c6fD", - "EthGenesisVault": "0x8B5c0d4c067Cf480766140B251B464de7F03B515", - "EthVaultFactory": "0x872870F43AD54e69CaC28456a9f397FCDcd4345C", - "EthPrivVaultFactory": "0xB3BE6f7544393f6FbAd8b92B2D7328891a8d8C4b", - "EthErc20VaultFactory": "0xD19dC15d0275c79984B69B961E77DA5D91E7125B", - "EthPrivErc20VaultFactory": "0x21C199766Bb6cD4217f02A496f01D1AD41F799a9", - "SharedMevEscrow": "0xb793c3D2Cec1d0F35fF88BCA7655B88A44669e4B", - "OsToken": "0xBcF097a3d3D846934694C47058A3cc9D5A6f7457", - "OsTokenConfig": "0x7869Fb1988554197d17F5aA846c98F7b01E8ddAc", - "PriceFeed": "0xe977B1fADBD28Dff25b093Dd48c02b07921F15E4", - "RewardSplitterFactory": "0x6A0A71220Bd8864Deee6d8ABc0113B5589ECf2f8" -} \ No newline at end of file diff --git a/deployments/holesky.json b/deployments/holesky.json index cf37cb85..3264d050 100644 --- a/deployments/holesky.json +++ b/deployments/holesky.json @@ -3,15 +3,17 @@ "Keeper": "0xB580799Bf7d62721D1a523f0FDF2f5Ed7BA4e259", "EthGenesisVault": "0xf42cEAFa21Beb670573f32C31485E84233AFDB6b", "EthFoxVault": "0x3c4ae629bf823475192124E02b9879D3C1fd4538", - "EthVaultFactory": "0x1428BB71261f01BbC03ce4eC7cEEA674f94b5F18", - "EthPrivVaultFactory": "0x9741f8e49fFa322714511b5D17bD052698eAFA43", - "EthErc20VaultFactory": "0x4C1140F4A5E3DD459De642A46bd1df6FBe287e1B", - "EthPrivErc20VaultFactory": "0x930A2D0ADEbF4E69Bb929F6456C3D4bcabf52796", + "EthVaultFactory": "0x61E12791C717B80CcE1a50bC97548fA281493e2a", + "EthPrivVaultFactory": "0x47Bf64605a71f5ea1FBE230735ab04669cC312D5", + "EthBlocklistVaultFactory": "0x0a57971758644A61279756591100c19e1691D068", + "EthErc20VaultFactory": "0x7a77934d32D78bFe8Dc1e23415b5679960a1c610", + "EthPrivErc20VaultFactory": "0x93a3f880E07B27dacA6Ef2d3C23E77DBd6294487", + "EthBlocklistErc20VaultFactory": "0x0F8c209445282d937DaC0eA0a6706590250F9aFD", "SharedMevEscrow": "0xc98F25BcAA6B812a07460f18da77AF8385be7b56", "OsToken": "0xF603c5A3F774F05d4D848A9bB139809790890864", "OsTokenConfig": "0x4483965Ed85cd5e67f2a7a0EB462aCcC37b23D72", "OsTokenVaultController": "0x7BbC1733ee018f103A9a9052a18fA9273255Cf36", "PriceFeed": "0xe31FAf135A6047Cbe595F91B4b6802cDB9B46E2b", - "RewardSplitterFactory": "0x6c56AC64457B8AeA1Bb8d1f5eA2d1E397C9c7a13", + "RewardSplitterFactory": "0x76747FeE60601be298E84A8a3D4D2D0dc82555F4", "CumulativeMerkleDrop": "0x6737277a4A9071AF88cCa91042d77b4237f368C4" } \ No newline at end of file diff --git a/helpers/constants.ts b/helpers/constants.ts index cdce38c5..3f58097d 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -51,8 +51,8 @@ export const NETWORKS: { // EthGenesisVault genesisVault: { admin: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', - poolEscrow: '0x253368DEBd5B3894D5A53516bE94CE4104bA4BD3', - rewardEthToken: '0x413C51fDF65668B3A1d434bC184a479E3B8e0f3f', + poolEscrow: '0x9f990e463674B9ABAeC2F19Abf18dAc4F523B48b', + rewardToken: '0xd57c19f20168406d162852515030e00e49bB7781', capacity: parseEther('1000000'), // 1m ETH feePercent: 500, // 5% }, @@ -116,7 +116,7 @@ export const NETWORKS: { genesisVault: { admin: '0xf330b5fE72E91d1a3782E65eED876CF3624c7802', poolEscrow: '0x2296e122c1a20Fca3CAc3371357BdAd3be0dF079', - rewardEthToken: '0x20BC832ca081b91433ff6c17f85701B6e92486c5', + rewardToken: '0x20BC832ca081b91433ff6c17f85701B6e92486c5', capacity: parseEther('1000000'), // 1m ETH feePercent: 500, // 5% }, diff --git a/helpers/types.ts b/helpers/types.ts index 55b0b41b..391e37e1 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -40,13 +40,13 @@ export type NetworkConfig = { genesisVault: { admin: string poolEscrow: string - rewardEthToken: string + rewardToken: string capacity: bigint feePercent: number } // EthFoxVault - foxVault: { + foxVault?: { admin: string capacity: bigint feePercent: number diff --git a/package.json b/package.json index 59a75d14..629bdf4c 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,9 @@ "coverage": "COVERAGE=true npm run compile && COVERAGE=true hardhat coverage", "precommit": "lint-staged", "node": "hardhat node", - "full-deploy:goerli": "hardhat eth-full-deploy --network goerli", "full-deploy:holesky": "hardhat eth-full-deploy --network holesky", "full-deploy:mainnet": "hardhat eth-full-deploy --network mainnet", - "full-deploy:local": "hardhat eth-full-deploy-local --network local" + "full-deploy:eth-local": "hardhat eth-full-deploy-local --network local" }, "repository": { "type": "git", diff --git a/tasks/eth-full-deploy-local.ts b/tasks/eth-full-deploy-local.ts index 7b03ada6..916fcde0 100644 --- a/tasks/eth-full-deploy-local.ts +++ b/tasks/eth-full-deploy-local.ts @@ -3,8 +3,9 @@ import '@openzeppelin/hardhat-upgrades/dist/type-extensions' import { simulateDeployImpl } from '@openzeppelin/hardhat-upgrades/dist/utils' import { task } from 'hardhat/config' import { deployContract, callContract } from '../helpers/utils' -import { ethValidatorsRegistry, NETWORKS } from '../helpers/constants' +import EthValidatorsRegistry from '../test/shared/artifacts/EthValidatorsRegistry.json' import { NetworkConfig, Networks } from '../helpers/types' +import { NETWORKS } from '../helpers/constants' const DEPLOYMENTS_DIR = 'deployments' @@ -21,6 +22,10 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ const rewardsMinOracles = 2 const validatorsMinOracles = 2 + if (networkConfig.foxVault === undefined) { + throw new Error('FoxVault config is missing') + } + // Create the signer for the mnemonic, connected to the provider with hardcoded fee data console.log('Deploying StakeWise V3 for Ethereum to', networkName, 'from', deployer.address) @@ -31,8 +36,8 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ // deploy ValidatorsRegistry const validatorsRegistry = await ( await ethers.getContractFactory( - ethValidatorsRegistry.abi, - ethValidatorsRegistry.bytecode, + EthValidatorsRegistry.abi, + EthValidatorsRegistry.bytecode, deployer ) ).deploy() @@ -119,7 +124,14 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ const osTokenConfigAddress = await osTokenConfig.getAddress() const factories: string[] = [] - for (const vaultType of ['EthVault', 'EthPrivVault', 'EthErc20Vault', 'EthPrivErc20Vault']) { + for (const vaultType of [ + 'EthVault', + 'EthPrivVault', + 'EthBlocklistVault', + 'EthErc20Vault', + 'EthPrivErc20Vault', + 'EthBlocklistErc20Vault', + ]) { // Deploy Vault Implementation const constructorArgs = [ keeperAddress, @@ -165,7 +177,7 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ osTokenConfigAddress, sharedMevEscrowAddress, networkConfig.genesisVault.poolEscrow, - networkConfig.genesisVault.rewardEthToken, + networkConfig.genesisVault.rewardToken, networkConfig.exitedAssetsClaimDelay, ] const genesisVaultImpl = await deployContract(hre, 'EthGenesisVault', constructorArgs) @@ -287,10 +299,13 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ const addresses = { VaultsRegistry: vaultsRegistryAddress, Keeper: keeperAddress, + EthFoxVault: foxVaultAddress, EthVaultFactory: factories[0], EthPrivVaultFactory: factories[1], - EthErc20VaultFactory: factories[2], - EthPrivErc20VaultFactory: factories[3], + EthBlocklistVaultFactory: factories[2], + EthErc20VaultFactory: factories[3], + EthPrivErc20VaultFactory: factories[4], + EthBlocklistErc20VaultFactory: factories[5], SharedMevEscrow: sharedMevEscrowAddress, OsToken: osTokenAddress, OsTokenConfig: osTokenConfigAddress, @@ -311,7 +326,7 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ console.log( 'NB! EthGenesisVault is not configured properly as ' + - 'it requires StakeWise V2 StakedEthToken and PoolEscrow contracts' + 'it requires StakeWise V2 tokens and PoolEscrow contracts' ) } ) diff --git a/tasks/eth-full-deploy.ts b/tasks/eth-full-deploy.ts index 6bb43c64..e84da15b 100644 --- a/tasks/eth-full-deploy.ts +++ b/tasks/eth-full-deploy.ts @@ -14,6 +14,10 @@ task('eth-full-deploy', 'deploys StakeWise V3 for Ethereum').setAction(async (ta const networkConfig: NetworkConfig = NETWORKS[networkName] const deployer = await ethers.provider.getSigner() + if (networkConfig.foxVault === undefined) { + throw new Error('FoxVault config is missing') + } + // Create the signer for the mnemonic, connected to the provider with hardcoded fee data console.log('Deploying StakeWise V3 for Ethereum to', networkName, 'from', deployer.address) @@ -130,7 +134,14 @@ task('eth-full-deploy', 'deploys StakeWise V3 for Ethereum').setAction(async (ta const osTokenConfigAddress = await osTokenConfig.getAddress() const factories: string[] = [] - for (const vaultType of ['EthVault', 'EthPrivVault', 'EthErc20Vault', 'EthPrivErc20Vault']) { + for (const vaultType of [ + 'EthVault', + 'EthPrivVault', + 'EthBlocklistVault', + 'EthErc20Vault', + 'EthPrivErc20Vault', + 'EthBlocklistErc20Vault', + ]) { // Deploy Vault Implementation const constructorArgs = [ keeperAddress, @@ -183,7 +194,7 @@ task('eth-full-deploy', 'deploys StakeWise V3 for Ethereum').setAction(async (ta osTokenConfigAddress, sharedMevEscrowAddress, networkConfig.genesisVault.poolEscrow, - networkConfig.genesisVault.rewardEthToken, + networkConfig.genesisVault.rewardToken, networkConfig.exitedAssetsClaimDelay, ] const genesisVaultImpl = await deployContract( @@ -334,10 +345,13 @@ task('eth-full-deploy', 'deploys StakeWise V3 for Ethereum').setAction(async (ta VaultsRegistry: vaultsRegistryAddress, Keeper: keeperAddress, EthGenesisVault: genesisVaultAddress, + EthFoxVault: foxVaultAddress, EthVaultFactory: factories[0], EthPrivVaultFactory: factories[1], - EthErc20VaultFactory: factories[2], - EthPrivErc20VaultFactory: factories[3], + EthBlocklistVaultFactory: factories[2], + EthErc20VaultFactory: factories[3], + EthPrivErc20VaultFactory: factories[4], + EthBlocklistErc20VaultFactory: factories[5], SharedMevEscrow: sharedMevEscrowAddress, OsToken: osTokenAddress, OsTokenConfig: osTokenConfigAddress, diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 51309ab0..26beb1a3 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,42 +10,42 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79638, + "gasUsed": 79660, } `; exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77206, + "gasUsed": 77278, } `; exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638183, + "gasUsed": 638255, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301781, + "gasUsed": 301853, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150242, + "gasUsed": 150264, } `; exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 145811, + "gasUsed": 145833, } `; @@ -59,6 +59,6 @@ Object { exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167342, + "gasUsed": 167364, } `; From 4bc8079d96a586e7d805e2c3a3299058e325c3ba Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sun, 10 Mar 2024 16:41:53 +0200 Subject: [PATCH 13/29] Fix genesis vault snapshot --- test/__snapshots__/EthGenesisVault.spec.ts.snap | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 26beb1a3..51309ab0 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,42 +10,42 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79660, + "gasUsed": 79638, } `; exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77278, + "gasUsed": 77206, } `; exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 638255, + "gasUsed": 638183, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 301853, + "gasUsed": 301781, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150264, + "gasUsed": 150242, } `; exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 145833, + "gasUsed": 145811, } `; @@ -59,6 +59,6 @@ Object { exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167364, + "gasUsed": 167342, } `; From 5b93a9c470a75719e691a1b94103dda52d04dd35 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sun, 10 Mar 2024 22:33:18 +0200 Subject: [PATCH 14/29] Fix genesis vault fork tests --- test/shared/fixtures.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index 8de3f899..d76c3751 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -939,7 +939,7 @@ export const ethVaultFixture = async function (): Promise { } else { poolEscrow = PoolEscrowMock__factory.connect(NETWORKS.mainnet.genesisVault.poolEscrow, dao) rewardEthToken = LegacyRewardTokenMock__factory.connect( - NETWORKS.mainnet.genesisVault.rewardEthToken, + NETWORKS.mainnet.genesisVault.rewardToken, dao ) } From ac9186384ca90c96849bbf3c155087245eec44f2 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Mon, 18 Mar 2024 13:43:32 +0200 Subject: [PATCH 15/29] Fix incorrect calculateExitedAssets interface outputs --- abi/IEthBlocklistErc20Vault.json | 6 +++--- abi/IEthBlocklistVault.json | 6 +++--- abi/IEthErc20Vault.json | 6 +++--- abi/IEthFoxVault.json | 6 +++--- abi/IEthGenesisVault.json | 6 +++--- abi/IEthPrivErc20Vault.json | 6 +++--- abi/IEthPrivVault.json | 6 +++--- abi/IEthVault.json | 6 +++--- abi/IVaultEnterExit.json | 6 +++--- abi/IVaultEthStaking.json | 6 +++--- abi/IVaultOsToken.json | 6 +++--- abi/IVaultToken.json | 6 +++--- contracts/interfaces/IVaultEnterExit.sol | 8 ++++---- 13 files changed, 40 insertions(+), 40 deletions(-) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index 072c01e1..7e33b6d8 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -712,17 +712,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index 3c0d4df8..d15eaa96 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -582,17 +582,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index aa1ff233..d582bf55 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -636,17 +636,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index dad4d020..91220f71 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -471,17 +471,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index 441f361b..fd94b983 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -569,17 +569,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 8c40441f..5af925c6 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -680,17 +680,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index eba6fdc6..d0dd07d1 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -550,17 +550,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IEthVault.json b/abi/IEthVault.json index de74fcaa..291b3c09 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -506,17 +506,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IVaultEnterExit.json b/abi/IVaultEnterExit.json index d513a237..e54a9f86 100644 --- a/abi/IVaultEnterExit.json +++ b/abi/IVaultEnterExit.json @@ -288,17 +288,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index 76ae7f82..f45b61b8 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -339,17 +339,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IVaultOsToken.json b/abi/IVaultOsToken.json index c0f42b08..1976d14a 100644 --- a/abi/IVaultOsToken.json +++ b/abi/IVaultOsToken.json @@ -455,17 +455,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/abi/IVaultToken.json b/abi/IVaultToken.json index a3e6bb4e..822fbcc0 100644 --- a/abi/IVaultToken.json +++ b/abi/IVaultToken.json @@ -418,17 +418,17 @@ "outputs": [ { "internalType": "uint256", - "name": "leftShares", + "name": "leftTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedShares", + "name": "exitedTickets", "type": "uint256" }, { "internalType": "uint256", - "name": "claimedAssets", + "name": "exitedAssets", "type": "uint256" } ], diff --git a/contracts/interfaces/IVaultEnterExit.sol b/contracts/interfaces/IVaultEnterExit.sol index 8eff2cba..2c400024 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -104,16 +104,16 @@ interface IVaultEnterExit is IVaultState { * @param timestamp The timestamp when the assets entered the exit queue * @param exitQueueIndex The exit queue index at which the shares were burned. * It can be looked up by calling `getExitQueueIndex`. Only relevant for V1 positions, otherwise pass 0. - * @return leftShares The number of shares that are still in the queue - * @return claimedShares The number of claimed shares - * @return claimedAssets The number of claimed assets + * @return leftTickets The number of tickets left in the queue + * @return exitedTickets The number of tickets that have already exited + * @return exitedAssets The number of assets that can be claimed */ function calculateExitedAssets( address receiver, uint256 positionTicket, uint256 timestamp, uint256 exitQueueIndex - ) external view returns (uint256 leftShares, uint256 claimedShares, uint256 claimedAssets); + ) external view returns (uint256 leftTickets, uint256 exitedTickets, uint256 exitedAssets); /** * @notice Claims assets that were withdrawn by the Vault. It can be called only after the `enterExitQueue` call by the `receiver`. From 9f0212aab72a69b08bc3c03a28d09c884a18aed8 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Thu, 21 Mar 2024 18:57:51 +0200 Subject: [PATCH 16/29] Extract Vault deposit data management to separate contract --- abi/Errors.json | 5 + abi/IDepositDataManager.json | 297 ++++++++++++ abi/IEthBlocklistErc20Vault.json | 99 ---- abi/IEthBlocklistVault.json | 99 ---- abi/IEthErc20Vault.json | 99 ---- abi/IEthFoxVault.json | 99 ---- abi/IEthGenesisVault.json | 99 ---- abi/IEthPrivErc20Vault.json | 99 ---- abi/IEthPrivVault.json | 99 ---- abi/IEthVault.json | 99 ---- abi/IVaultEthStaking.json | 99 ---- abi/IVaultValidators.json | 99 ---- contracts/interfaces/IDepositDataManager.sol | 115 +++++ contracts/interfaces/IVaultEnterExit.sol | 6 +- contracts/interfaces/IVaultState.sol | 4 +- contracts/interfaces/IVaultValidators.sol | 46 +- contracts/libraries/Errors.sol | 1 + contracts/misc/DepositDataManager.sol | 173 +++++++ contracts/mocks/EthPrivVaultV3Mock.sol | 2 + contracts/mocks/EthVaultMock.sol | 2 + contracts/mocks/EthVaultV3Mock.sol | 2 + contracts/mocks/EthVaultV4Mock.sol | 2 + .../ethereum/EthBlocklistErc20Vault.sol | 4 +- .../vaults/ethereum/EthBlocklistVault.sol | 4 +- contracts/vaults/ethereum/EthErc20Vault.sol | 4 + contracts/vaults/ethereum/EthGenesisVault.sol | 10 +- .../vaults/ethereum/EthPrivErc20Vault.sol | 3 + contracts/vaults/ethereum/EthPrivVault.sol | 3 + contracts/vaults/ethereum/EthVault.sol | 4 + .../vaults/ethereum/custom/EthFoxVault.sol | 4 + contracts/vaults/modules/VaultEthStaking.sol | 51 ++- contracts/vaults/modules/VaultState.sol | 6 +- contracts/vaults/modules/VaultValidators.sol | 168 +++---- test/DepositDataManager.spec.ts | 424 ++++++++++++++++++ test/EthBlocklistErc20Vault.spec.ts | 9 +- test/EthBlocklistVault.spec.ts | 9 +- test/EthErc20Vault.spec.ts | 15 +- test/EthFoxVault.spec.ts | 12 +- test/EthGenesisVault.spec.ts | 40 +- test/EthPrivErc20Vault.spec.ts | 9 +- test/EthPrivVault.spec.ts | 13 +- test/EthVault.burn.spec.ts | 14 +- test/EthVault.deposit.spec.ts | 20 +- test/EthVault.liquidate.spec.ts | 7 +- test/EthVault.mint.spec.ts | 7 +- test/EthVault.multicall.spec.ts | 11 +- test/EthVault.redeem.spec.ts | 7 +- test/EthVault.register.spec.ts | 343 ++++++-------- test/EthVault.settings.spec.ts | 49 +- test/EthVault.state.spec.ts | 7 +- test/EthVault.upgrade.spec.ts | 14 +- test/EthVault.whitelist.spec.ts | 10 +- test/KeeperRewards.spec.ts | 15 +- test/KeeperValidators.spec.ts | 105 +++-- test/OsToken.spec.ts | 21 +- test/PriceFeed.test.ts | 22 +- test/RewardSplitter.spec.ts | 24 +- test/VaultsRegistry.spec.ts | 1 + .../DepositDataManager.spec.ts.snap | 36 ++ .../EthBlocklistErc20Vault.spec.ts.snap | 6 +- .../EthBlocklistVault.spec.ts.snap | 4 +- test/__snapshots__/EthErc20Vault.spec.ts.snap | 6 +- test/__snapshots__/EthFoxVault.spec.ts.snap | 12 +- .../EthGenesisVault.spec.ts.snap | 22 +- .../EthPrivErc20Vault.spec.ts.snap | 6 +- test/__snapshots__/EthPrivVault.spec.ts.snap | 2 +- .../EthVault.deposit.spec.ts.snap | 8 +- .../EthVault.liquidate.spec.ts.snap | 4 +- test/__snapshots__/EthVault.mint.spec.ts.snap | 4 +- .../EthVault.multicall.spec.ts.snap | 4 +- .../EthVault.redeem.spec.ts.snap | 4 +- .../EthVault.register.spec.ts.snap | 8 +- .../EthVault.settings.spec.ts.snap | 13 +- .../__snapshots__/EthVault.state.spec.ts.snap | 6 +- .../__snapshots__/EthVault.token.spec.ts.snap | 6 +- .../EthVault.upgrade.spec.ts.snap | 14 +- .../EthVault.whitelist.spec.ts.snap | 4 +- .../EthVault.withdraw.spec.ts.snap | 10 +- .../EthVaultFactory.spec.ts.snap | 8 +- test/__snapshots__/KeeperRewards.spec.ts.snap | 24 +- .../KeeperValidators.spec.ts.snap | 14 +- .../__snapshots__/RewardSplitter.spec.ts.snap | 8 +- .../__snapshots__/VaultsRegistry.spec.ts.snap | 2 +- test/shared/fixtures.ts | 25 +- test/shared/rewards.ts | 11 +- test/shared/validators.ts | 53 ++- 86 files changed, 1778 insertions(+), 1660 deletions(-) create mode 100644 abi/IDepositDataManager.json create mode 100644 contracts/interfaces/IDepositDataManager.sol create mode 100644 contracts/misc/DepositDataManager.sol create mode 100644 test/DepositDataManager.spec.ts create mode 100644 test/__snapshots__/DepositDataManager.spec.ts.snap diff --git a/abi/Errors.json b/abi/Errors.json index 56dcc0c3..f5bfbdac 100644 --- a/abi/Errors.json +++ b/abi/Errors.json @@ -214,6 +214,11 @@ "name": "UpgradeFailed", "type": "error" }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, { "inputs": [], "name": "ZeroAddress", diff --git a/abi/IDepositDataManager.json b/abi/IDepositDataManager.json new file mode 100644 index 00000000..9be53c95 --- /dev/null +++ b/abi/IDepositDataManager.json @@ -0,0 +1,297 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositDataManager", + "type": "address" + } + ], + "name": "DepositDataManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "depositDataRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositDataManager", + "type": "address" + } + ], + "name": "DepositDataMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "depositDataRoot", + "type": "bytes32" + } + ], + "name": "DepositDataRootUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "name": "depositDataIndexes", + "outputs": [ + { + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "name": "depositDataRoots", + "outputs": [ + { + "internalType": "bytes32", + "name": "depositDataRoot", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "name": "getDepositDataManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "depositDataRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "validatorIndex", + "type": "uint256" + }, + { + "internalType": "address", + "name": "depositDataManager", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "validatorsRegistryRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "validators", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "string", + "name": "exitSignaturesIpfsHash", + "type": "string" + } + ], + "internalType": "struct IKeeperValidators.ApprovalParams", + "name": "keeperParams", + "type": "tuple" + }, + { + "internalType": "uint256[]", + "name": "indexes", + "type": "uint256[]" + }, + { + "internalType": "bool[]", + "name": "proofFlags", + "type": "bool[]" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "registerValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "internalType": "address", + "name": "depositDataManager", + "type": "address" + } + ], + "name": "setDepositDataManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "depositDataRoot", + "type": "bytes32" + } + ], + "name": "setDepositDataRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index 7e33b6d8..a20105c3 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -1247,66 +1247,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1366,19 +1306,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "symbol", @@ -1601,32 +1528,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index d15eaa96..681538a9 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -1029,66 +1029,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1148,19 +1088,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -1304,32 +1231,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index d582bf55..7fe7e899 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -1171,66 +1171,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1277,19 +1217,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "symbol", @@ -1494,32 +1421,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index 91220f71..8dfae5e2 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -837,66 +837,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -956,19 +896,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -1112,32 +1039,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index fd94b983..0e979212 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -1040,66 +1040,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1146,19 +1086,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -1284,32 +1211,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 5af925c6..d3fd4667 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -1215,66 +1215,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1321,19 +1261,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1569,32 +1496,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index d0dd07d1..9c184958 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -997,66 +997,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1103,19 +1043,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1272,32 +1199,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthVault.json b/abi/IEthVault.json index 291b3c09..aac3151e 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -953,66 +953,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -1059,19 +999,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -1197,32 +1124,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "vaultId", diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index f45b61b8..bb31b994 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -634,66 +634,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -740,19 +680,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -878,32 +805,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "withdrawableAssets", diff --git a/abi/IVaultValidators.json b/abi/IVaultValidators.json index 9baee071..c3d002ed 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -313,66 +313,6 @@ "internalType": "struct IKeeperValidators.ApprovalParams", "name": "keeperParams", "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "registerValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "validatorsRegistryRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "validators", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signatures", - "type": "bytes" - }, - { - "internalType": "string", - "name": "exitSignaturesIpfsHash", - "type": "string" - } - ], - "internalType": "struct IKeeperValidators.ApprovalParams", - "name": "keeperParams", - "type": "tuple" - }, - { - "internalType": "uint256[]", - "name": "indexes", - "type": "uint256[]" - }, - { - "internalType": "bool[]", - "name": "proofFlags", - "type": "bool[]" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" } ], "name": "registerValidators", @@ -419,19 +359,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_validatorsRoot", - "type": "bytes32" - } - ], - "name": "setValidatorsRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalAssets", @@ -506,32 +433,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "validatorIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorsRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "withdrawableAssets", diff --git a/contracts/interfaces/IDepositDataManager.sol b/contracts/interfaces/IDepositDataManager.sol new file mode 100644 index 00000000..2872de4c --- /dev/null +++ b/contracts/interfaces/IDepositDataManager.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IKeeperValidators} from './IKeeperValidators.sol'; + +/** + * @title IDepositDataManager + * @author StakeWise + * @notice Defines the interface for DepositDataManager + */ +interface IDepositDataManager { + /** + * @notice Event emitted on deposit data manager update + * @param vault The address of the vault + * @param depositDataManager The address of the new deposit data manager + */ + event DepositDataManagerUpdated(address indexed vault, address depositDataManager); + + /** + * @notice Event emitted on deposit data root update + * @param vault The address of the vault + * @param depositDataRoot The new deposit data Merkle tree root + */ + event DepositDataRootUpdated(address indexed vault, bytes32 depositDataRoot); + + /** + * @notice Event emitted on deposit data migration + * @param vault The address of the vault + * @param depositDataRoot The deposit data root + * @param validatorIndex The index of the next validator to be registered + * @param depositDataManager The address of the deposit data manager + */ + event DepositDataMigrated( + address indexed vault, + bytes32 depositDataRoot, + uint256 validatorIndex, + address depositDataManager + ); + + /** + * @notice The vault deposit data index + * @param vault The address of the vault + * @return validatorIndex The index of the next validator to be registered + */ + function depositDataIndexes(address vault) external view returns (uint256 validatorIndex); + + /** + * @notice The vault deposit data root + * @param vault The address of the vault + * @return depositDataRoot The deposit data root + */ + function depositDataRoots(address vault) external view returns (bytes32 depositDataRoot); + + /** + * @notice The vault deposit data manager. Defaults to the vault admin if not set. + * @param vault The address of the vault + * @return depositDataManager The address of the deposit data manager + */ + function getDepositDataManager(address vault) external view returns (address); + + /** + * @notice Function for setting the deposit data manager for the vault. Can only be called by the vault admin. + * @param vault The address of the vault + * @param depositDataManager The address of the new deposit data manager + */ + function setDepositDataManager(address vault, address depositDataManager) external; + + /** + * @notice Function for setting the deposit data root for the vault. Can only be called by the deposit data manager. + * @param vault The address of the vault + * @param depositDataRoot The new deposit data Merkle tree root + */ + function setDepositDataRoot(address vault, bytes32 depositDataRoot) external; + + /** + * @notice Function for registering single validator + * @param vault The address of the vault + * @param keeperParams The parameters for getting approval from Keeper oracles + * @param proof The proof used to verify that the validator is part of the deposit data merkle tree + */ + function registerValidator( + address vault, + IKeeperValidators.ApprovalParams calldata keeperParams, + bytes32[] calldata proof + ) external; + + /** + * @notice Function for registering multiple validators + * @param vault The address of the vault + * @param keeperParams The parameters for getting approval from Keeper oracles + * @param indexes The indexes of the leaves for the merkle tree multi proof verification + * @param proofFlags The multi proof flags for the merkle tree verification + * @param proof The proof used for the merkle tree verification + */ + function registerValidators( + address vault, + IKeeperValidators.ApprovalParams calldata keeperParams, + uint256[] calldata indexes, + bool[] calldata proofFlags, + bytes32[] calldata proof + ) external; + + /** + * @notice Function for migrating the deposit data of the Vault. Can only be called once by a vault during an upgrade. + * @param depositDataRoot The current deposit data root + * @param validatorIndex The current index of the next validator to be registered + * @param depositDataManager The address of the deposit data manager + */ + function migrate( + bytes32 depositDataRoot, + uint256 validatorIndex, + address depositDataManager + ) external; +} diff --git a/contracts/interfaces/IVaultEnterExit.sol b/contracts/interfaces/IVaultEnterExit.sol index 2c400024..1bd280cf 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -27,7 +27,7 @@ interface IVaultEnterExit is IVaultState { ); /** - * @notice Event emitted on redeem + * @notice Event emitted on redeem (deprecated) * @param owner The address that owns the shares * @param receiver The address that received withdrawn assets * @param assets The total number of withdrawn assets @@ -36,7 +36,7 @@ interface IVaultEnterExit is IVaultState { event Redeemed(address indexed owner, address indexed receiver, uint256 assets, uint256 shares); /** - * @notice Event emitted on shares added to the V1 exit queue + * @notice Event emitted on shares added to the V1 exit queue (deprecated) * @param owner The address that owns the shares * @param receiver The address that will receive withdrawn assets * @param positionTicket The exit queue ticket that was assigned to the position @@ -90,7 +90,7 @@ interface IVaultEnterExit is IVaultState { ) external returns (uint256 positionTicket); /** - * @notice Get the exit queue index to claim exited assets from + * @notice Get the exit queue index to claim exited assets from (deprecated) * @param positionTicket The exit queue position ticket to get the index for * @return The exit queue index that should be used to claim exited assets. * Returns -1 in case such index does not exist. diff --git a/contracts/interfaces/IVaultState.sol b/contracts/interfaces/IVaultState.sol index e82b1681..9a2fdb8e 100644 --- a/contracts/interfaces/IVaultState.sol +++ b/contracts/interfaces/IVaultState.sol @@ -12,7 +12,7 @@ import {IVaultFee} from './IVaultFee.sol'; */ interface IVaultState is IVaultFee { /** - * @notice Event emitted on checkpoint creation (V1 exit queue) + * @notice Event emitted on checkpoint creation (deprecated) * @param shares The number of burned shares * @param assets The amount of exited assets */ @@ -51,7 +51,7 @@ interface IVaultState is IVaultFee { function withdrawableAssets() external view returns (uint256); /** - * @notice Queued Shares + * @notice Queued Shares (deprecated) * @return The total number of shares queued for exit */ function queuedShares() external view returns (uint128); diff --git a/contracts/interfaces/IVaultValidators.sol b/contracts/interfaces/IVaultValidators.sol index 53cbcb21..fc04b637 100644 --- a/contracts/interfaces/IVaultValidators.sol +++ b/contracts/interfaces/IVaultValidators.sol @@ -26,7 +26,7 @@ interface IVaultValidators is IVaultAdmin, IVaultState { event KeysManagerUpdated(address indexed caller, address indexed keysManager); /** - * @notice Event emitted on validators merkle tree root update + * @notice Event emitted on validators merkle tree root update (deprecated) * @param caller The address of the function caller * @param validatorsRoot The new validators merkle tree root */ @@ -34,55 +34,19 @@ interface IVaultValidators is IVaultAdmin, IVaultState { /** * @notice The Vault keys manager address - * @return The address that can update validators merkle tree root + * @return The address that can register validators */ function keysManager() external view returns (address); /** - * @notice The Vault validators root - * @return The merkle tree root to use for verifying validators deposit data - */ - function validatorsRoot() external view returns (bytes32); - - /** - * @notice The Vault validator index - * @return The index of the next validator to be registered in the current deposit data file - */ - function validatorIndex() external view returns (uint256); - - /** - * @notice Function for registering single validator + * @notice Function for registering single or multiple validators * @param keeperParams The parameters for getting approval from Keeper oracles - * @param proof The proof used to verify that the validator is part of the validators merkle tree */ - function registerValidator( - IKeeperValidators.ApprovalParams calldata keeperParams, - bytes32[] calldata proof - ) external; + function registerValidators(IKeeperValidators.ApprovalParams calldata keeperParams) external; /** - * @notice Function for registering multiple validators - * @param keeperParams The parameters for getting approval from Keeper oracles - * @param indexes The indexes of the leaves for the merkle tree multi proof verification - * @param proofFlags The multi proof flags for the merkle tree verification - * @param proof The proof used for the merkle tree verification - */ - function registerValidators( - IKeeperValidators.ApprovalParams calldata keeperParams, - uint256[] calldata indexes, - bool[] calldata proofFlags, - bytes32[] calldata proof - ) external; - - /** - * @notice Function for updating the keys manager. Can only be called by the admin. + * @notice Function for updating the keys manager. Can only be called by the admin. Default is the deposit data manager contract. * @param _keysManager The new keys manager address */ function setKeysManager(address _keysManager) external; - - /** - * @notice Function for updating the validators merkle tree root. Can only be called by the keys manager. - * @param _validatorsRoot The new validators merkle tree root - */ - function setValidatorsRoot(bytes32 _validatorsRoot) external; } diff --git a/contracts/libraries/Errors.sol b/contracts/libraries/Errors.sol index 871c3544..902b922b 100644 --- a/contracts/libraries/Errors.sol +++ b/contracts/libraries/Errors.sol @@ -52,4 +52,5 @@ library Errors { error InvalidCheckpointValue(); error MaxOraclesExceeded(); error ExitRequestNotProcessed(); + error ValueNotChanged(); } diff --git a/contracts/misc/DepositDataManager.sol b/contracts/misc/DepositDataManager.sol new file mode 100644 index 00000000..05daae0e --- /dev/null +++ b/contracts/misc/DepositDataManager.sol @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {MerkleProof} from '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol'; +import {IDepositDataManager} from '../interfaces/IDepositDataManager.sol'; +import {IKeeperValidators} from '../interfaces/IKeeperValidators.sol'; +import {IVaultAdmin} from '../interfaces/IVaultAdmin.sol'; +import {IVaultValidators} from '../interfaces/IVaultValidators.sol'; +import {IVaultsRegistry} from '../interfaces/IVaultsRegistry.sol'; +import {Errors} from '../libraries/Errors.sol'; + +/** + * @title DepositDataManager + * @author StakeWise + * @notice Defines the functionality for the Vault's deposit data management + */ +contract DepositDataManager is IDepositDataManager { + IVaultsRegistry private immutable _vaultsRegistry; + + /// @inheritdoc IDepositDataManager + mapping(address => uint256) public override depositDataIndexes; + + /// @inheritdoc IDepositDataManager + mapping(address => bytes32) public override depositDataRoots; + + mapping(address => address) private _depositDataManagers; + mapping(address => bool) private _migrated; + + /** + * @dev Constructor + * @param vaultsRegistry The address of the vaults registry contract + */ + constructor(address vaultsRegistry) { + _vaultsRegistry = IVaultsRegistry(vaultsRegistry); + } + + /// @inheritdoc IDepositDataManager + function getDepositDataManager(address vault) public view override returns (address) { + address depositDataManager = _depositDataManagers[vault]; + return depositDataManager == address(0) ? IVaultAdmin(vault).admin() : depositDataManager; + } + + /// @inheritdoc IDepositDataManager + function setDepositDataManager(address vault, address depositDataManager) external override { + if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + // only vault admin can set deposit data manager + if (msg.sender != IVaultAdmin(vault).admin()) revert Errors.AccessDenied(); + + // update deposit data manager + _depositDataManagers[vault] = depositDataManager; + emit DepositDataManagerUpdated(vault, depositDataManager); + } + + /// @inheritdoc IDepositDataManager + function setDepositDataRoot(address vault, bytes32 depositDataRoot) external override { + if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + if (msg.sender != getDepositDataManager(vault)) revert Errors.AccessDenied(); + if (depositDataRoots[vault] == depositDataRoot) revert Errors.ValueNotChanged(); + + depositDataRoots[vault] = depositDataRoot; + // reset validator index on every root update + depositDataIndexes[vault] = 0; + emit DepositDataRootUpdated(vault, depositDataRoot); + } + + /// @inheritdoc IDepositDataManager + function registerValidator( + address vault, + IKeeperValidators.ApprovalParams calldata keeperParams, + bytes32[] calldata proof + ) external override { + if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + + // register validator + IVaultValidators(vault).registerValidators(keeperParams); + + // SLOAD to memory + uint256 currentIndex = depositDataIndexes[vault]; + bytes32 depositDataRoot = depositDataRoots[vault]; + + // check matches merkle root and next validator index + if ( + !MerkleProof.verifyCalldata( + proof, + depositDataRoot, + keccak256(bytes.concat(keccak256(abi.encode(keeperParams.validators, currentIndex)))) + ) + ) { + revert Errors.InvalidProof(); + } + + // increment index for the next validator + unchecked { + // cannot realistically overflow + depositDataIndexes[vault] = currentIndex + 1; + } + } + + /// @inheritdoc IDepositDataManager + function registerValidators( + address vault, + IKeeperValidators.ApprovalParams calldata keeperParams, + uint256[] calldata indexes, + bool[] calldata proofFlags, + bytes32[] calldata proof + ) external override { + if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + + // register validator + IVaultValidators(vault).registerValidators(keeperParams); + + // SLOAD to memory + uint256 currentIndex = depositDataIndexes[vault]; + bytes32 depositDataRoot = depositDataRoots[vault]; + + // define leaves for multiproof + uint256 validatorsCount = indexes.length; + if (validatorsCount == 0) revert Errors.InvalidValidators(); + bytes32[] memory leaves = new bytes32[](validatorsCount); + + // calculate validator length + uint256 validatorLength = keeperParams.validators.length / validatorsCount; + if (validatorLength == 0) revert Errors.InvalidValidators(); + + // calculate leaves + { + uint256 startIndex; + uint256 endIndex; + for (uint256 i = 0; i < validatorsCount; ) { + endIndex += validatorLength; + leaves[indexes[i]] = keccak256( + bytes.concat( + keccak256(abi.encode(keeperParams.validators[startIndex:endIndex], currentIndex)) + ) + ); + + startIndex = endIndex; + unchecked { + // cannot realistically overflow + ++currentIndex; + ++i; + } + } + } + + // check matches merkle root and next validator index + if (!MerkleProof.multiProofVerifyCalldata(proof, proofFlags, depositDataRoot, leaves)) { + revert Errors.InvalidProof(); + } + + // increment index for the next validator + depositDataIndexes[vault] = currentIndex; + } + + /// @inheritdoc IDepositDataManager + function migrate( + bytes32 depositDataRoot, + uint256 validatorIndex, + address depositDataManager + ) external override { + if (!_vaultsRegistry.vaults(msg.sender) || _migrated[msg.sender]) { + revert Errors.AccessDenied(); + } + depositDataRoots[msg.sender] = depositDataRoot; + depositDataIndexes[msg.sender] = validatorIndex; + _depositDataManagers[msg.sender] = depositDataManager; + + // only allow migration once + _migrated[msg.sender] = true; + emit DepositDataMigrated(msg.sender, depositDataRoot, validatorIndex, depositDataManager); + } +} diff --git a/contracts/mocks/EthPrivVaultV3Mock.sol b/contracts/mocks/EthPrivVaultV3Mock.sol index 32a7df19..14f572d1 100644 --- a/contracts/mocks/EthPrivVaultV3Mock.sol +++ b/contracts/mocks/EthPrivVaultV3Mock.sol @@ -15,6 +15,7 @@ contract EthPrivVaultV3Mock is EthPrivVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthPrivVault( @@ -24,6 +25,7 @@ contract EthPrivVaultV3Mock is EthPrivVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultMock.sol b/contracts/mocks/EthVaultMock.sol index 693af617..2ee95491 100644 --- a/contracts/mocks/EthVaultMock.sol +++ b/contracts/mocks/EthVaultMock.sol @@ -26,6 +26,7 @@ contract EthVaultMock is EthVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthVault( @@ -35,6 +36,7 @@ contract EthVaultMock is EthVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultV3Mock.sol b/contracts/mocks/EthVaultV3Mock.sol index 5e816610..54650dd0 100644 --- a/contracts/mocks/EthVaultV3Mock.sol +++ b/contracts/mocks/EthVaultV3Mock.sol @@ -15,6 +15,7 @@ contract EthVaultV3Mock is EthVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthVault( @@ -24,6 +25,7 @@ contract EthVaultV3Mock is EthVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultV4Mock.sol b/contracts/mocks/EthVaultV4Mock.sol index 085c687c..d73e8211 100644 --- a/contracts/mocks/EthVaultV4Mock.sol +++ b/contracts/mocks/EthVaultV4Mock.sol @@ -13,6 +13,7 @@ contract EthVaultV4Mock is EthVaultV3Mock { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthVaultV3Mock( @@ -22,6 +23,7 @@ contract EthVaultV4Mock is EthVaultV3Mock { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol index 9d505f76..9ae63750 100644 --- a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -36,6 +36,7 @@ contract EthBlocklistErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -46,6 +47,7 @@ contract EthBlocklistErc20Vault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthErc20Vault( @@ -55,6 +57,7 @@ contract EthBlocklistErc20Vault is osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} @@ -72,7 +75,6 @@ contract EthBlocklistErc20Vault is ); // blocklist manager is initially set to admin address __VaultBlocklist_init(_admin); - __EthErc20Vault_initV2(); } /// @inheritdoc IVaultEthStaking diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol index a1c84758..b25c0ee3 100644 --- a/contracts/vaults/ethereum/EthBlocklistVault.sol +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -30,6 +30,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -40,6 +41,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthVault( @@ -49,6 +51,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} @@ -66,7 +69,6 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock ); // blocklist manager is initially set to admin address __VaultBlocklist_init(_admin); - __EthVault_initV2(); } /// @inheritdoc IVaultEthStaking diff --git a/contracts/vaults/ethereum/EthErc20Vault.sol b/contracts/vaults/ethereum/EthErc20Vault.sol index 52a1a02f..b7058dee 100644 --- a/contracts/vaults/ethereum/EthErc20Vault.sol +++ b/contracts/vaults/ethereum/EthErc20Vault.sol @@ -53,6 +53,7 @@ contract EthErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -63,9 +64,11 @@ contract EthErc20Vault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) + VaultValidators(depositDataManager) VaultEnterExit(exitingAssetsClaimDelay) VaultOsToken(osTokenVaultController, osTokenConfig) VaultMev(sharedMevEscrow) @@ -186,6 +189,7 @@ contract EthErc20Vault is */ function __EthErc20Vault_initV2() internal onlyInitializing { __VaultState_initV2(); + __VaultValidators_initV2(); } /** diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index 4ea47010..52746796 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -44,6 +44,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param poolEscrow The address of the pool escrow from StakeWise v2 * @param rewardEthToken The address of the rETH2 token from StakeWise v2 * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking @@ -56,6 +57,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, address poolEscrow, address rewardEthToken, uint256 exitingAssetsClaimDelay @@ -67,6 +69,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) { @@ -239,11 +242,10 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { /// @inheritdoc VaultValidators function _registerMultipleValidators( - bytes calldata validators, - uint256[] calldata indexes - ) internal virtual override(VaultValidators, VaultEthStaking) returns (bytes32[] memory leaves) { + bytes calldata validators + ) internal virtual override(VaultValidators, VaultEthStaking) { _pullWithdrawals(); - return super._registerMultipleValidators(validators, indexes); + return super._registerMultipleValidators(validators); } /** diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index 2577c287..6f467dea 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -31,6 +31,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -41,6 +42,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthErc20Vault( @@ -50,6 +52,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index 1652a4fd..ec05b2f9 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -30,6 +30,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -40,6 +41,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) EthVault( @@ -49,6 +51,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthVault.sol b/contracts/vaults/ethereum/EthVault.sol index 68689eca..da041dc4 100644 --- a/contracts/vaults/ethereum/EthVault.sol +++ b/contracts/vaults/ethereum/EthVault.sol @@ -49,6 +49,7 @@ contract EthVault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -59,9 +60,11 @@ contract EthVault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) + VaultValidators(depositDataManager) VaultEnterExit(exitingAssetsClaimDelay) VaultOsToken(osTokenVaultController, osTokenConfig) VaultMev(sharedMevEscrow) @@ -134,6 +137,7 @@ contract EthVault is */ function __EthVault_initV2() internal onlyInitializing { __VaultState_initV2(); + __VaultValidators_initV2(); } /** diff --git a/contracts/vaults/ethereum/custom/EthFoxVault.sol b/contracts/vaults/ethereum/custom/EthFoxVault.sol index 6023e038..296a311f 100644 --- a/contracts/vaults/ethereum/custom/EthFoxVault.sol +++ b/contracts/vaults/ethereum/custom/EthFoxVault.sol @@ -46,6 +46,7 @@ contract EthFoxVault is * @param _vaultsRegistry The address of the VaultsRegistry contract * @param _validatorsRegistry The contract address used for registering validators in beacon chain * @param sharedMevEscrow The address of the shared MEV escrow + * @param depositDataManager The address of the DepositDataManager contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -54,9 +55,11 @@ contract EthFoxVault is address _vaultsRegistry, address _validatorsRegistry, address sharedMevEscrow, + address depositDataManager, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) + VaultValidators(depositDataManager) VaultEnterExit(exitingAssetsClaimDelay) VaultMev(sharedMevEscrow) { @@ -147,6 +150,7 @@ contract EthFoxVault is */ function __EthFoxVault_initV2() internal onlyInitializing { __VaultState_initV2(); + __VaultValidators_initV2(); } /** diff --git a/contracts/vaults/modules/VaultEthStaking.sol b/contracts/vaults/modules/VaultEthStaking.sol index 45a35d9d..bacee358 100644 --- a/contracts/vaults/modules/VaultEthStaking.sol +++ b/contracts/vaults/modules/VaultEthStaking.sol @@ -67,52 +67,38 @@ abstract contract VaultEthStaking is publicKey, _withdrawalCredentials(), validator[48:144], - bytes32(validator[144:_validatorLength]) + bytes32(validator[144:validator.length]) ); - emit ValidatorRegistered(publicKey); } /// @inheritdoc VaultValidators - function _registerMultipleValidators( - bytes calldata validators, - uint256[] calldata indexes - ) internal virtual override returns (bytes32[] memory leaves) { - // SLOAD to memory - uint256 currentValIndex = validatorIndex; - + function _registerMultipleValidators(bytes calldata validators) internal virtual override { uint256 startIndex; uint256 endIndex; + uint256 validatorsCount = validators.length / _validatorLength(); + bytes memory withdrawalCredentials = _withdrawalCredentials(); bytes calldata validator; bytes calldata publicKey; - uint256 validatorsCount = indexes.length; - leaves = new bytes32[](validatorsCount); - uint256 validatorDeposit = _validatorDeposit(); - bytes memory withdrawalCreds = _withdrawalCredentials(); - - for (uint256 i = 0; i < validatorsCount; i++) { + for (uint256 i = 0; i < validatorsCount; ) { unchecked { // cannot realistically overflow - endIndex += _validatorLength; + endIndex += _validatorLength(); } validator = validators[startIndex:endIndex]; - leaves[indexes[i]] = keccak256( - bytes.concat(keccak256(abi.encode(validator, currentValIndex))) - ); publicKey = validator[:48]; - // slither-disable-next-line arbitrary-send-eth - IEthValidatorsRegistry(_validatorsRegistry).deposit{value: validatorDeposit}( + IEthValidatorsRegistry(_validatorsRegistry).deposit{value: _validatorDeposit()}( publicKey, - withdrawalCreds, + withdrawalCredentials, validator[48:144], - bytes32(validator[144:_validatorLength]) + bytes32(validator[144:_validatorLength()]) ); + emit ValidatorRegistered(publicKey); startIndex = endIndex; unchecked { // cannot realistically overflow - ++currentValIndex; + ++i; } - emit ValidatorRegistered(publicKey); } } @@ -130,10 +116,23 @@ abstract contract VaultEthStaking is } /// @inheritdoc VaultValidators - function _validatorDeposit() internal pure override returns (uint256) { + function _validatorLength() internal pure virtual override returns (uint256) { + return 176; + } + + /// @inheritdoc VaultValidators + function _validatorDeposit() internal pure virtual override returns (uint256) { return 32 ether; } + /** + * @dev Internal function for calculating Vault withdrawal credentials + * @return The credentials used for the validators withdrawals + */ + function _withdrawalCredentials() internal view virtual returns (bytes memory) { + return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)); + } + /** * @dev Initializes the VaultEthStaking contract */ diff --git a/contracts/vaults/modules/VaultState.sol b/contracts/vaults/modules/VaultState.sol index 8fc26f0d..f945fe80 100644 --- a/contracts/vaults/modules/VaultState.sol +++ b/contracts/vaults/modules/VaultState.sol @@ -24,10 +24,10 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint128 internal _totalAssets; /// @inheritdoc IVaultState - uint128 public override queuedShares; - uint128 internal _unclaimedAssets; + uint128 public override queuedShares; // deprecated + uint128 internal _unclaimedAssets; // deprecated + ExitQueue.History internal _exitQueue; // deprecated - ExitQueue.History internal _exitQueue; mapping(bytes32 => uint256) internal _exitRequests; mapping(address => uint256) internal _balances; diff --git a/contracts/vaults/modules/VaultValidators.sol b/contracts/vaults/modules/VaultValidators.sol index 8a54a73a..ebf220f5 100644 --- a/contracts/vaults/modules/VaultValidators.sol +++ b/contracts/vaults/modules/VaultValidators.sol @@ -5,6 +5,7 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; import {MerkleProof} from '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol'; import {IKeeperValidators} from '../../interfaces/IKeeperValidators.sol'; +import {IDepositDataManager} from '../../interfaces/IDepositDataManager.sol'; import {IVaultValidators} from '../../interfaces/IVaultValidators.sol'; import {Errors} from '../../libraries/Errors.sol'; import {VaultImmutables} from './VaultImmutables.sol'; @@ -23,160 +24,99 @@ abstract contract VaultValidators is VaultState, IVaultValidators { - uint256 internal constant _validatorLength = 176; + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address private immutable _depositDataManager; - /// @inheritdoc IVaultValidators - bytes32 public override validatorsRoot; + /// deprecated. Deposit data management is moved to DepositDataManager contract + bytes32 private _validatorsRoot; - /// @inheritdoc IVaultValidators - uint256 public override validatorIndex; + /// deprecated. Deposit data management is moved to DepositDataManager contract + uint256 private _validatorIndex; address private _keysManager; + /** + * @dev Constructor + * @dev Since the immutable variable value is stored in the bytecode, + * its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage. + * @param depositDataManager The address of the deposit data manager contract + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor(address depositDataManager) { + _depositDataManager = depositDataManager; + } + /// @inheritdoc IVaultValidators function keysManager() public view override returns (address) { // SLOAD to memory address keysManager_ = _keysManager; - // if keysManager is not set, use admin address - return keysManager_ == address(0) ? admin : keysManager_; + // if keysManager is not set, use deposit data manager contract address + return keysManager_ == address(0) ? _depositDataManager : keysManager_; } /// @inheritdoc IVaultValidators - function registerValidator( - IKeeperValidators.ApprovalParams calldata keeperParams, - bytes32[] calldata proof + function registerValidators( + IKeeperValidators.ApprovalParams calldata keeperParams ) external override { - _checkHarvested(); - // get approval from oracles IKeeperValidators(_keeper).approveValidators(keeperParams); - // check enough withdrawable assets - if (withdrawableAssets() < _validatorDeposit()) revert Errors.InsufficientAssets(); - - // check validator length is valid - if (keeperParams.validators.length != _validatorLength) revert Errors.InvalidValidator(); - - // SLOAD to memory - uint256 currentIndex = validatorIndex; - - // check matches merkle root and next validator index - if ( - !MerkleProof.verifyCalldata( - proof, - validatorsRoot, - keccak256(bytes.concat(keccak256(abi.encode(keeperParams.validators, currentIndex)))) - ) - ) { - revert Errors.InvalidProof(); - } - - // register validator - _registerSingleValidator(keeperParams.validators); - - // increment index for the next validator - unchecked { - // cannot realistically overflow - validatorIndex = currentIndex + 1; - } - } - - /// @inheritdoc IVaultValidators - function registerValidators( - IKeeperValidators.ApprovalParams calldata keeperParams, - uint256[] calldata indexes, - bool[] calldata proofFlags, - bytes32[] calldata proof - ) external override { + // check vault is up to date _checkHarvested(); - // get approval from oracles - IKeeperValidators(_keeper).approveValidators(keeperParams); - - // check enough withdrawable assets - uint256 validatorsCount = indexes.length; - if (withdrawableAssets() < _validatorDeposit() * validatorsCount) { - revert Errors.InsufficientAssets(); - } + // check access + if (msg.sender != keysManager()) revert Errors.AccessDenied(); // check validators length is valid + uint256 validatorLength = _validatorLength(); + uint256 validatorsCount = keeperParams.validators.length / validatorLength; unchecked { if ( - validatorsCount == 0 || validatorsCount * _validatorLength != keeperParams.validators.length + validatorsCount == 0 || validatorsCount * validatorLength != keeperParams.validators.length ) { revert Errors.InvalidValidators(); } } - // check matches merkle root and next validator index - if ( - !MerkleProof.multiProofVerifyCalldata( - proof, - proofFlags, - validatorsRoot, - _registerMultipleValidators(keeperParams.validators, indexes) - ) - ) { - revert Errors.InvalidProof(); + // check enough withdrawable assets + if (withdrawableAssets() < _validatorDeposit() * validatorsCount) { + revert Errors.InsufficientAssets(); } - // increment index for the next validator - unchecked { - // cannot realistically overflow - validatorIndex += validatorsCount; + if (keeperParams.validators.length == validatorLength) { + // register single validator + _registerSingleValidator(keeperParams.validators); + } else { + // register multiple validators + _registerMultipleValidators(keeperParams.validators); } } /// @inheritdoc IVaultValidators function setKeysManager(address keysManager_) external override { _checkAdmin(); - if (keysManager_ == address(0)) revert Errors.ZeroAddress(); // update keysManager address _keysManager = keysManager_; emit KeysManagerUpdated(msg.sender, keysManager_); } - /// @inheritdoc IVaultValidators - function setValidatorsRoot(bytes32 _validatorsRoot) external override { - if (msg.sender != keysManager()) revert Errors.AccessDenied(); - _setValidatorsRoot(_validatorsRoot); - } - /** - * @dev Internal function for updating the validators root externally or from the initializer - * @param _validatorsRoot The new validators merkle tree root + * @dev Internal function for registering validator. Must emit ValidatorRegistered event. + * @param validator The validator registration data */ - function _setValidatorsRoot(bytes32 _validatorsRoot) private { - validatorsRoot = _validatorsRoot; - // reset validator index on every root update - validatorIndex = 0; - emit ValidatorsRootUpdated(msg.sender, _validatorsRoot); - } + function _registerSingleValidator(bytes calldata validator) internal virtual; /** - * @dev Internal function for calculating Vault withdrawal credentials - * @return The credentials used for the validators withdrawals + * @dev Internal function for registering multiple validators. Must emit ValidatorRegistered event for every validator. + * @param validators The validators registration data */ - function _withdrawalCredentials() internal view returns (bytes memory) { - return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)); - } + function _registerMultipleValidators(bytes calldata validators) internal virtual; /** - * @dev Internal function for registering single validator. Must emit ValidatorRegistered event. - * @param validator The concatenation of the validator public key, signature and deposit data root + * @dev Internal function for defining the length of the validator data + * @return The length of the single validator data */ - function _registerSingleValidator(bytes calldata validator) internal virtual; - - /** - * @dev Internal function for registering multiple validators. Must emit ValidatorRegistered event for every validator. - * @param validators The concatenation of the validators' public key, signature and deposit data root - * @param indexes The indexes of the leaves for the merkle tree multi proof verification - * @return leaves The leaves used for the merkle tree multi proof verification - */ - function _registerMultipleValidators( - bytes calldata validators, - uint256[] calldata indexes - ) internal virtual returns (bytes32[] memory leaves); + function _validatorLength() internal pure virtual returns (uint256); /** * @dev Internal function for fetching validator deposit amount @@ -191,6 +131,22 @@ abstract contract VaultValidators is if (capacity() < _validatorDeposit()) revert Errors.InvalidCapacity(); } + /** + * @dev Initializes the V2 of the VaultValidators contract + */ + function __VaultValidators_initV2() internal onlyInitializing { + IDepositDataManager(_depositDataManager).migrate( + _validatorsRoot, + _validatorIndex, + _keysManager + ); + + // clean up variables + delete _validatorsRoot; + delete _validatorIndex; + delete _keysManager; + } + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. diff --git a/test/DepositDataManager.spec.ts b/test/DepositDataManager.spec.ts new file mode 100644 index 00000000..f496bd23 --- /dev/null +++ b/test/DepositDataManager.spec.ts @@ -0,0 +1,424 @@ +import { ethers } from 'hardhat' +import { Contract, Signer, Wallet } from 'ethers' +import { UintNumberType } from '@chainsafe/ssz' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { ThenArg } from '../helpers/types' +import { EthVault, IKeeperValidators, Keeper, DepositDataManager } from '../typechain-types' +import snapshotGasCost from './shared/snapshotGasCost' +import { expect } from './shared/expect' +import { setBalance, toHexString } from './shared/utils' +import { + createEthValidatorsData, + EthValidatorsData, + exitSignatureIpfsHashes, + getEthValidatorsSigningData, + getValidatorProof, + getValidatorsMultiProof, + getWithdrawalCredentials, + ValidatorsMultiProof, +} from './shared/validators' +import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' +import { + MAX_UINT256, + PANIC_CODES, + VALIDATORS_DEADLINE, + VALIDATORS_MIN_ORACLES, + ZERO_ADDRESS, + ZERO_BYTES32, +} from './shared/constants' + +const gwei = 1000000000n +const uintSerializer = new UintNumberType(8) + +describe('DepositDataManager', () => { + const validatorDeposit = ethers.parseEther('32') + const capacity = MAX_UINT256 + const feePercent = 1000 + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + const deadline = VALIDATORS_DEADLINE + + let admin: Signer, other: Wallet, manager: Wallet, dao: Wallet + let vault: EthVault, + keeper: Keeper, + validatorsRegistry: Contract, + vaultsRegistry: VaultRegistry, + depositDataManager: DepositDataManager + let validatorsData: EthValidatorsData + let validatorsRegistryRoot: string + + let createVault: ThenArg>['createEthVault'] + + before('create fixture loader', async () => { + ;[dao, admin, other, manager] = await (ethers as any).getSigners() + }) + + beforeEach('deploy fixture', async () => { + ;({ + validatorsRegistry, + createEthVault: createVault, + keeper, + depositDataManager, + vaultsRegistry, + } = await loadFixture(ethVaultFixture)) + + vault = await createVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + admin = await ethers.getImpersonatedSigner(await vault.admin()) + validatorsData = await createEthValidatorsData(vault) + validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() + await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: validatorDeposit }) + }) + + describe('deposit data manager update', () => { + it('fails for non-vault', async () => { + await expect( + depositDataManager.connect(admin).setDepositDataManager(other.address, manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + + it('fails for non-admin', async () => { + await expect( + depositDataManager + .connect(other) + .setDepositDataManager(await vault.getAddress(), manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + }) + + it('succeeds', async () => { + const vaultAddr = await vault.getAddress() + const adminAddr = await admin.getAddress() + expect(await depositDataManager.getDepositDataManager(vaultAddr)).to.eq(adminAddr) + const receipt = await depositDataManager + .connect(admin) + .setDepositDataManager(vaultAddr, manager.address) + await expect(receipt) + .to.emit(depositDataManager, 'DepositDataManagerUpdated') + .withArgs(vaultAddr, manager.address) + expect(await depositDataManager.getDepositDataManager(vaultAddr)).to.eq(manager.address) + await snapshotGasCost(receipt) + }) + }) + + describe('deposit data root update', () => { + beforeEach('set manager', async () => { + await depositDataManager + .connect(admin) + .setDepositDataManager(await vault.getAddress(), manager.address) + }) + + it('fails for invalid vault', async () => { + await expect( + depositDataManager.connect(manager).setDepositDataRoot(other.address, validatorsData.root) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + + it('fails from non-manager', async () => { + await expect( + depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), validatorsData.root) + ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + }) + + it('fails for same root', async () => { + const vaultAddr = await vault.getAddress() + await depositDataManager.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) + await expect( + depositDataManager.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) + ).to.be.revertedWithCustomError(depositDataManager, 'ValueNotChanged') + }) + + it('success', async () => { + const vaultAddr = await vault.getAddress() + const receipt = await depositDataManager + .connect(manager) + .setDepositDataRoot(vaultAddr, validatorsData.root) + await expect(receipt) + .to.emit(depositDataManager, 'DepositDataRootUpdated') + .withArgs(vaultAddr, validatorsData.root) + await snapshotGasCost(receipt) + }) + }) + + describe('single validator', () => { + let validator: Buffer + let proof: string[] + let approvalParams: IKeeperValidators.ApprovalParamsStruct + + beforeEach(async () => { + validator = validatorsData.validators[0] + proof = getValidatorProof(validatorsData.tree, validator, 0) + await depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), validatorsData.root) + const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] + const signatures = getOraclesSignatures( + await getEthValidatorsSigningData( + validator, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot + ), + VALIDATORS_MIN_ORACLES + ) + approvalParams = { + validatorsRegistryRoot, + validators: validator, + signatures, + exitSignaturesIpfsHash, + deadline, + } + }) + + it('fails for invalid vault', async () => { + await expect( + depositDataManager.registerValidator(other.address, approvalParams, proof) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + + it('fails with invalid proof', async () => { + const invalidProof = getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) + await expect( + depositDataManager.registerValidator(await vault.getAddress(), approvalParams, invalidProof) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidProof') + }) + + it('succeeds', async () => { + const index = await validatorsRegistry.get_deposit_count() + const receipt = await depositDataManager.registerValidator( + await vault.getAddress(), + approvalParams, + proof + ) + const publicKey = `0x${validator.subarray(0, 48).toString('hex')}` + await expect(receipt).to.emit(vault, 'ValidatorRegistered').withArgs(publicKey) + await expect(receipt) + .to.emit(validatorsRegistry, 'DepositEvent') + .withArgs( + publicKey, + toHexString(getWithdrawalCredentials(await vault.getAddress())), + toHexString(Buffer.from(uintSerializer.serialize(Number(validatorDeposit / gwei)))), + toHexString(validator.subarray(48, 144)), + index + ) + expect(await depositDataManager.depositDataIndexes(await vault.getAddress())).to.eq(1) + + await depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), ZERO_BYTES32) + expect(await depositDataManager.depositDataIndexes(await vault.getAddress())).to.eq(0) + await snapshotGasCost(receipt) + }) + }) + + describe('multiple validators', () => { + let validators: Buffer[] + let indexes: number[] + let approvalParams: IKeeperValidators.ApprovalParamsStruct + let multiProof: ValidatorsMultiProof + let signatures: Buffer + + beforeEach(async () => { + multiProof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ + ...Array(validatorsData.validators.length).keys(), + ]) + validators = validatorsData.validators + const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] + const sortedVals = multiProof.leaves.map((v) => v[0]) + const vaultAddr = await vault.getAddress() + await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) + indexes = validators.map((v) => sortedVals.indexOf(v)) + const balance = + validatorDeposit * BigInt(validators.length) + + (await vault.totalExitingAssets()) + + (await ethers.provider.getBalance(vaultAddr)) + await setBalance(vaultAddr, balance) + signatures = getOraclesSignatures( + await getEthValidatorsSigningData( + Buffer.concat(validators), + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot + ), + VALIDATORS_MIN_ORACLES + ) + approvalParams = { + validatorsRegistryRoot, + validators: Buffer.concat(validators), + signatures, + exitSignaturesIpfsHash, + deadline, + } + }) + + it('fails for invalid vault', async () => { + await expect( + depositDataManager.registerValidators( + other.address, + approvalParams, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + + it('fails with invalid validators count', async () => { + const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] + await expect( + depositDataManager.registerValidators( + await vault.getAddress(), + { + validatorsRegistryRoot, + validators: Buffer.from(''), + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + Buffer.from(''), + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot + ), + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(vault, 'InvalidValidators') + }) + + it('fails with invalid proof', async () => { + const invalidMultiProof = getValidatorsMultiProof( + validatorsData.tree, + validators.slice(1), + [...Array(validatorsData.validators.length).keys()].slice(1) + ) + + await expect( + depositDataManager.registerValidators( + await vault.getAddress(), + approvalParams, + indexes, + invalidMultiProof.proofFlags, + invalidMultiProof.proof + ) + ).to.be.revertedWithCustomError(depositDataManager, 'MerkleProofInvalidMultiproof') + }) + + it('fails with invalid indexes', async () => { + const vaultAddr = await vault.getAddress() + await expect( + depositDataManager.registerValidators( + vaultAddr, + approvalParams, + [], + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidValidators') + + await expect( + depositDataManager.registerValidators( + vaultAddr, + approvalParams, + indexes.map((i) => i + 1), + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithPanic(PANIC_CODES.OUT_OF_BOUND_INDEX) + + await expect( + depositDataManager.registerValidators( + vaultAddr, + approvalParams, + indexes.sort(() => 0.5 - Math.random()), + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidProof') + }) + + it('succeeds', async () => { + const startIndex = uintSerializer.deserialize( + ethers.getBytes(await validatorsRegistry.get_deposit_count()) + ) + const vaultAddress = await vault.getAddress() + const receipt = await depositDataManager.registerValidators( + vaultAddress, + approvalParams, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + for (let i = 0; i < validators.length; i++) { + const validator = validators[i] + const publicKey = toHexString(validator.subarray(0, 48)) + await expect(receipt).to.emit(vault, 'ValidatorRegistered').withArgs(publicKey) + await expect(receipt) + .to.emit(validatorsRegistry, 'DepositEvent') + .withArgs( + publicKey, + toHexString(getWithdrawalCredentials(await vault.getAddress())), + toHexString(Buffer.from(uintSerializer.serialize(Number(validatorDeposit / gwei)))), + toHexString(validator.subarray(48, 144)), + toHexString(Buffer.from(uintSerializer.serialize(startIndex + i))) + ) + } + expect(await depositDataManager.depositDataIndexes(vaultAddress)).to.eq(validators.length) + await snapshotGasCost(receipt) + }) + }) + + describe('migrate', () => { + const validatorIndex = 2 + + beforeEach('set manager', async () => { + await vaultsRegistry.connect(dao).addVault(other.address) + }) + + it('fails for non-vault', async () => { + await expect( + depositDataManager + .connect(admin) + .migrate(validatorsData.root, validatorIndex, manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + }) + + it('fails for already migrated', async () => { + await depositDataManager + .connect(other) + .migrate(validatorsData.root, validatorIndex, manager.address) + + await expect( + depositDataManager + .connect(other) + .migrate(validatorsData.root, validatorIndex, manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + }) + + it('succeeds', async () => { + const receipt = await depositDataManager + .connect(other) + .migrate(validatorsData.root, validatorIndex, manager.address) + await expect(receipt) + .to.emit(depositDataManager, 'DepositDataMigrated') + .withArgs(other.address, validatorsData.root, validatorIndex, manager.address) + expect(await depositDataManager.getDepositDataManager(other.address)).to.eq(manager.address) + expect(await depositDataManager.depositDataRoots(other.address)).to.eq(validatorsData.root) + expect(await depositDataManager.depositDataIndexes(other.address)).to.eq(validatorIndex) + await snapshotGasCost(receipt) + }) + }) +}) diff --git a/test/EthBlocklistErc20Vault.spec.ts b/test/EthBlocklistErc20Vault.spec.ts index 964da341..9945a8b4 100644 --- a/test/EthBlocklistErc20Vault.spec.ts +++ b/test/EthBlocklistErc20Vault.spec.ts @@ -5,6 +5,7 @@ import { EthBlocklistErc20Vault, IKeeperRewards, Keeper, + DepositDataManager, OsTokenVaultController, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' @@ -31,7 +32,8 @@ describe('EthBlocklistErc20Vault', () => { let vault: EthBlocklistErc20Vault, keeper: Keeper, validatorsRegistry: Contract, - osTokenVaultController: OsTokenVaultController + osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager beforeEach('deploy fixtures', async () => { ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() @@ -47,6 +49,7 @@ describe('EthBlocklistErc20Vault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController + depositDataManager = fixture.depositDataManager }) it('has id', async () => { @@ -114,7 +117,7 @@ describe('EthBlocklistErc20Vault', () => { }) it('cannot update state and call by blocked sender', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -184,7 +187,7 @@ describe('EthBlocklistErc20Vault', () => { let osTokenShares: bigint beforeEach(async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthBlocklistVault.spec.ts b/test/EthBlocklistVault.spec.ts index 51e93812..ec6f543a 100644 --- a/test/EthBlocklistVault.spec.ts +++ b/test/EthBlocklistVault.spec.ts @@ -6,6 +6,7 @@ import { IKeeperRewards, Keeper, OsTokenVaultController, + DepositDataManager, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -29,7 +30,8 @@ describe('EthBlocklistVault', () => { let vault: EthBlocklistVault, keeper: Keeper, validatorsRegistry: Contract, - osTokenVaultController: OsTokenVaultController + osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager beforeEach('deploy fixtures', async () => { ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() @@ -43,6 +45,7 @@ describe('EthBlocklistVault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController + depositDataManager = fixture.depositDataManager }) it('has id', async () => { @@ -75,7 +78,7 @@ describe('EthBlocklistVault', () => { }) it('cannot update state and call by blocked sender', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -145,7 +148,7 @@ describe('EthBlocklistVault', () => { let osTokenShares: bigint beforeEach(async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthErc20Vault.spec.ts b/test/EthErc20Vault.spec.ts index 441667d4..9f22b633 100644 --- a/test/EthErc20Vault.spec.ts +++ b/test/EthErc20Vault.spec.ts @@ -8,6 +8,7 @@ import { VaultsRegistry, OsTokenConfig, SharedMevEscrow, + DepositDataManager, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { @@ -44,7 +45,8 @@ describe('EthErc20Vault', () => { osTokenVaultController: OsTokenVaultController, vaultsRegistry: VaultsRegistry, osTokenConfig: OsTokenConfig, - sharedMevEscrow: SharedMevEscrow + sharedMevEscrow: SharedMevEscrow, + depositDataManager: DepositDataManager beforeEach('deploy fixtures', async () => { ;[sender, receiver, admin] = (await (ethers as any).getSigners()).slice(1, 4) @@ -63,6 +65,7 @@ describe('EthErc20Vault', () => { osTokenConfig = fixture.osTokenConfig vaultsRegistry = fixture.vaultsRegistry sharedMevEscrow = fixture.sharedMevEscrow + depositDataManager = fixture.depositDataManager }) it('has id', async () => { @@ -118,7 +121,7 @@ describe('EthErc20Vault', () => { }) it('enter exit queue emits transfer event', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) expect(await vault.totalExitingAssets()).to.be.eq(0) const totalExitingBefore = await vault.totalExitingAssets() const totalAssetsBefore = await vault.totalAssets() @@ -168,7 +171,7 @@ describe('EthErc20Vault', () => { await vault .connect(admin) .deposit(await admin.getAddress(), ZERO_ADDRESS, { value: validatorDeposit }) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) const rewardsTree = await updateRewards(keeper, [ { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, @@ -197,7 +200,7 @@ describe('EthErc20Vault', () => { }) it('cannot transfer vault shares when unharvested and osToken minted', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const assets = ethers.parseEther('1') const shares = await vault.convertToShares(assets) const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) @@ -217,7 +220,7 @@ describe('EthErc20Vault', () => { }) it('cannot transfer vault shares when LTV is violated', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const assets = ethers.parseEther('2') const shares = await vault.convertToShares(assets) const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) @@ -234,7 +237,7 @@ describe('EthErc20Vault', () => { }) it('can transfer vault shares when LTV is not violated', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const assets = ethers.parseEther('2') const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) const transferShares = await vault.convertToShares(ethers.parseEther('0.1')) diff --git a/test/EthFoxVault.spec.ts b/test/EthFoxVault.spec.ts index f1649753..39d61760 100644 --- a/test/EthFoxVault.spec.ts +++ b/test/EthFoxVault.spec.ts @@ -2,7 +2,7 @@ import { ethers } from 'hardhat' import keccak256 from 'keccak256' import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { Keeper, IKeeperRewards, EthFoxVault } from '../typechain-types' +import { Keeper, IKeeperRewards, EthFoxVault, DepositDataManager } from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -22,7 +22,10 @@ describe('EthFoxVault', () => { const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' let sender: Wallet, blocklistManager: Wallet, admin: Signer, other: Wallet - let vault: EthFoxVault, keeper: Keeper, validatorsRegistry: Contract + let vault: EthFoxVault, + keeper: Keeper, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createFoxVault: ThenArg>['createEthFoxVault'] @@ -35,6 +38,7 @@ describe('EthFoxVault', () => { createEthFoxVault: createFoxVault, keeper, validatorsRegistry, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createFoxVault(admin, { capacity, @@ -127,7 +131,7 @@ describe('EthFoxVault', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -220,7 +224,7 @@ describe('EthFoxVault', () => { }) it('blocklist manager can eject all of the user assets for collateralized vault', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const tx = await vault.connect(blocklistManager).ejectUser(sender.address) const positionTicket = await extractExitPositionTicket(tx) diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 4ee10c43..83a72967 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -1,6 +1,12 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' -import { EthGenesisVault, Keeper, PoolEscrowMock, LegacyRewardTokenMock } from '../typechain-types' +import { + EthGenesisVault, + Keeper, + PoolEscrowMock, + LegacyRewardTokenMock, + DepositDataManager, +} from '../typechain-types' import { createDepositorMock, ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { expect } from './shared/expect' import keccak256 from 'keccak256' @@ -43,7 +49,10 @@ describe('EthGenesisVault', () => { const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' const deadline = VALIDATORS_DEADLINE let admin: Signer, other: Wallet - let vault: EthGenesisVault, keeper: Keeper, validatorsRegistry: Contract + let vault: EthGenesisVault, + keeper: Keeper, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let poolEscrow: PoolEscrowMock let rewardEthToken: LegacyRewardTokenMock @@ -56,13 +65,7 @@ describe('EthGenesisVault', () => { async function collatEthVault() { if (MAINNET_FORK.enabled) return - await collateralizeEthVault( - vault, - keeper, - validatorsRegistry, - admin, - await poolEscrow.getAddress() - ) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) } beforeEach('deploy fixtures', async () => { @@ -70,6 +73,7 @@ describe('EthGenesisVault', () => { const fixture = await loadFixture(ethVaultFixture) keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry + depositDataManager = fixture.depositDataManager ;[vault, rewardEthToken, poolEscrow] = await fixture.createEthGenesisVault(admin, { capacity, feePercent, @@ -278,7 +282,13 @@ describe('EthGenesisVault', () => { await setBalance(vaultAddr, 0n) await setBalance(poolEscrowAddr, validatorDeposit + vaultBalance + poolEscrowBalance) expect(await vault.withdrawableAssets()).to.be.greaterThanOrEqual(validatorDeposit) - const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin) + const tx = await registerEthValidator( + vault, + keeper, + depositDataManager, + admin, + validatorsRegistry + ) await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, validatorDeposit + vaultBalance + poolEscrowBalance) @@ -290,7 +300,10 @@ describe('EthGenesisVault', () => { await collatEthVault() const validatorsData = await createEthValidatorsData(vault) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() - await vault.connect(admin).setValidatorsRoot(validatorsData.root) + const vaultAddr = await vault.getAddress() + // reset validator index + await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, ZERO_BYTES32) + await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) const proof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ ...Array(validatorsData.validators.length).keys(), ]) @@ -318,7 +331,6 @@ describe('EthGenesisVault', () => { deadline, } - const vaultAddr = await vault.getAddress() const vaultBalance = await ethers.provider.getBalance(vaultAddr) const poolEscrowAddr = await poolEscrow.getAddress() const poolEscrowBalance = await ethers.provider.getBalance(poolEscrowAddr) @@ -326,7 +338,9 @@ describe('EthGenesisVault', () => { await setBalance(vaultAddr, 0n) await setBalance(poolEscrowAddr, assets + vaultBalance + poolEscrowBalance) - const tx = await vault.registerValidators(approveParams, indexes, proof.proofFlags, proof.proof) + const tx = await depositDataManager + .connect(admin) + .registerValidators(vaultAddr, approveParams, indexes, proof.proofFlags, proof.proof) await expect(tx) .to.emit(poolEscrow, 'Withdrawn') .withArgs(vaultAddr, vaultAddr, assets + vaultBalance + poolEscrowBalance) diff --git a/test/EthPrivErc20Vault.spec.ts b/test/EthPrivErc20Vault.spec.ts index 52f4fcac..1357f15f 100644 --- a/test/EthPrivErc20Vault.spec.ts +++ b/test/EthPrivErc20Vault.spec.ts @@ -6,6 +6,7 @@ import { IKeeperRewards, Keeper, OsTokenVaultController, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' @@ -26,7 +27,8 @@ describe('EthPrivErc20Vault', () => { let vault: EthPrivErc20Vault, keeper: Keeper, validatorsRegistry: Contract, - osTokenVaultController: OsTokenVaultController + osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager let createPrivateVault: ThenArg>['createEthPrivErc20Vault'] @@ -37,6 +39,7 @@ describe('EthPrivErc20Vault', () => { keeper, validatorsRegistry, osTokenVaultController, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -71,7 +74,7 @@ describe('EthPrivErc20Vault', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const vaultReward = ethers.parseEther('1') const tree = await updateRewards(keeper, [ { reward: vaultReward, unlockedMevReward: 0n, vault: await vault.getAddress() }, @@ -188,7 +191,7 @@ describe('EthPrivErc20Vault', () => { beforeEach(async () => { await vault.connect(admin).updateWhitelist(sender.address, true) await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthPrivVault.spec.ts b/test/EthPrivVault.spec.ts index 746b6c33..c0d46ecf 100644 --- a/test/EthPrivVault.spec.ts +++ b/test/EthPrivVault.spec.ts @@ -1,7 +1,12 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthPrivVault, Keeper, OsTokenVaultController } from '../typechain-types' +import { + EthPrivVault, + Keeper, + OsTokenVaultController, + DepositDataManager, +} from '../typechain-types' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' import { ZERO_ADDRESS } from './shared/constants' @@ -18,7 +23,8 @@ describe('EthPrivVault', () => { let vault: EthPrivVault, keeper: Keeper, validatorsRegistry: Contract, - osTokenVaultController: OsTokenVaultController + osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager beforeEach('deploy fixtures', async () => { ;[sender, admin, other] = await (ethers as any).getSigners() @@ -32,6 +38,7 @@ describe('EthPrivVault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController + depositDataManager = fixture.depositDataManager }) it('has id', async () => { @@ -55,7 +62,7 @@ describe('EthPrivVault', () => { beforeEach(async () => { await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(admin).updateWhitelist(sender.address, true) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) diff --git a/test/EthVault.burn.spec.ts b/test/EthVault.burn.spec.ts index 6f54e51b..4be174d9 100644 --- a/test/EthVault.burn.spec.ts +++ b/test/EthVault.burn.spec.ts @@ -1,7 +1,13 @@ import { ethers } from 'hardhat' import { Contract, ContractTransactionReceipt, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, Keeper, OsTokenVaultController, OsToken } from '../typechain-types' +import { + EthVault, + Keeper, + OsTokenVaultController, + OsToken, + DepositDataManager, +} from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' import { createUnknownVaultMock, ethVaultFixture } from './shared/fixtures' @@ -24,7 +30,8 @@ describe('EthVault - burn', () => { keeper: Keeper, osTokenVaultController: OsTokenVaultController, osToken: OsToken, - validatorsRegistry: Contract + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] @@ -36,12 +43,13 @@ describe('EthVault - burn', () => { validatorsRegistry, osToken, osTokenVaultController, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) // collateralize vault - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, ZERO_ADDRESS, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(osTokenAssets) await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) diff --git a/test/EthVault.deposit.spec.ts b/test/EthVault.deposit.spec.ts index de7e52f3..39fc11b1 100644 --- a/test/EthVault.deposit.spec.ts +++ b/test/EthVault.deposit.spec.ts @@ -1,7 +1,14 @@ import { ethers } from 'hardhat' import { Contract, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, EthVaultMock, IKeeperRewards, Keeper, SharedMevEscrow } from '../typechain-types' +import { + EthVault, + EthVaultMock, + IKeeperRewards, + Keeper, + SharedMevEscrow, + DepositDataManager, +} from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' @@ -19,7 +26,11 @@ describe('EthVault - deposit', () => { const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' const referrer = '0x' + '1'.repeat(40) let sender: Wallet, receiver: Wallet, admin: Wallet, other: Wallet - let vault: EthVault, keeper: Keeper, mevEscrow: SharedMevEscrow, validatorsRegistry: Contract + let vault: EthVault, + keeper: Keeper, + mevEscrow: SharedMevEscrow, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] @@ -32,6 +43,7 @@ describe('EthVault - deposit', () => { keeper, validatorsRegistry, sharedMevEscrow: mevEscrow, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault( admin, @@ -115,7 +127,7 @@ describe('EthVault - deposit', () => { }) it('fails when not harvested', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await updateRewards(keeper, [ { reward: ethers.parseEther('5'), @@ -141,7 +153,7 @@ describe('EthVault - deposit', () => { await vault .connect(other) .deposit(other.address, referrer, { value: ethers.parseEther('32') }) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault.connect(other).enterExitQueue(ethers.parseEther('32'), other.address) let vaultReward = ethers.parseEther('10') diff --git a/test/EthVault.liquidate.spec.ts b/test/EthVault.liquidate.spec.ts index 3cd7f67d..59bfb945 100644 --- a/test/EthVault.liquidate.spec.ts +++ b/test/EthVault.liquidate.spec.ts @@ -7,6 +7,7 @@ import { OsToken, OsTokenConfig, OsTokenVaultController, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' @@ -40,7 +41,8 @@ describe('EthVault - liquidate', () => { osTokenVaultController: OsTokenVaultController, osToken: OsToken, osTokenConfig: OsTokenConfig, - validatorsRegistry: Contract + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] @@ -53,13 +55,14 @@ describe('EthVault - liquidate', () => { osTokenVaultController, osToken, osTokenConfig, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) await osTokenVaultController.connect(dao).setFeePercent(0) // collateralize vault - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const tx = await vault.connect(owner).deposit(owner.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) diff --git a/test/EthVault.mint.spec.ts b/test/EthVault.mint.spec.ts index b3069bf3..0548f90c 100644 --- a/test/EthVault.mint.spec.ts +++ b/test/EthVault.mint.spec.ts @@ -7,6 +7,7 @@ import { OsToken, VaultsRegistry, OsTokenVaultController, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -36,7 +37,8 @@ describe('EthVault - mint', () => { vaultsRegistry: VaultsRegistry, osTokenVaultController: OsTokenVaultController, osToken: OsToken, - validatorsRegistry: Contract + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] @@ -49,12 +51,13 @@ describe('EthVault - mint', () => { osToken, osTokenVaultController, vaultsRegistry, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) // collateralize vault - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const tx = await vault.connect(sender).deposit(sender.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) diff --git a/test/EthVault.multicall.spec.ts b/test/EthVault.multicall.spec.ts index b3853acc..20363457 100644 --- a/test/EthVault.multicall.spec.ts +++ b/test/EthVault.multicall.spec.ts @@ -7,6 +7,7 @@ import { Keeper, MulticallMock, OwnMevEscrow__factory, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -35,7 +36,10 @@ describe('EthVault - multicall', () => { const metadataIpfsHash = '/ipfs/QmanU2bk9VsJuxhBmvfgXaC44fXpcC8DNHNxPZKMpNXo37' let sender: Wallet, admin: Signer - let vault: EthVault, keeper: Keeper, validatorsRegistry: Contract + let vault: EthVault, + keeper: Keeper, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] @@ -45,6 +49,7 @@ describe('EthVault - multicall', () => { createEthVault: createVault, keeper, validatorsRegistry, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault( admin, @@ -66,7 +71,7 @@ describe('EthVault - multicall', () => { await vault .connect(sender) .deposit(sender.address, referrer, { value: ethers.parseEther('32') }) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) await setBalance(await mevEscrow.getAddress(), ethers.parseEther('10')) const userShares = await vault.getShares(sender.address) @@ -164,7 +169,7 @@ describe('EthVault - multicall', () => { it('fails to deposit, enter exit queue, update state and claim in one transaction', async () => { const vaultAddr = await vault.getAddress() - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) expect(await vault.isStateUpdateRequired()).to.eq(false) expect(await keeper.canHarvest(vaultAddr)).to.eq(false) diff --git a/test/EthVault.redeem.spec.ts b/test/EthVault.redeem.spec.ts index 274fe4ee..2c86660f 100644 --- a/test/EthVault.redeem.spec.ts +++ b/test/EthVault.redeem.spec.ts @@ -8,6 +8,7 @@ import { OsToken, OsTokenConfig, OsTokenVaultController, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' @@ -51,7 +52,8 @@ describe('EthVault - redeem osToken', () => { osTokenVaultController: OsTokenVaultController, osToken: OsToken, osTokenConfig: OsTokenConfig, - validatorsRegistry: Contract + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] @@ -64,13 +66,14 @@ describe('EthVault - redeem osToken', () => { osTokenVaultController, osToken, osTokenConfig, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) await osTokenVaultController.connect(dao).setFeePercent(0) // collateralize vault - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const tx = await vault.connect(owner).deposit(owner.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) diff --git a/test/EthVault.register.spec.ts b/test/EthVault.register.spec.ts index 5ec5684b..a64e6a1b 100644 --- a/test/EthVault.register.spec.ts +++ b/test/EthVault.register.spec.ts @@ -13,19 +13,16 @@ import { EthValidatorsData, exitSignatureIpfsHashes, getEthValidatorsSigningData, - getValidatorProof, - getValidatorsMultiProof, getWithdrawalCredentials, - ValidatorsMultiProof, } from './shared/validators' import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { MAX_UINT256, - PANIC_CODES, VALIDATORS_DEADLINE, VALIDATORS_MIN_ORACLES, ZERO_ADDRESS, } from './shared/constants' +import { getHarvestParams, updateRewards } from './shared/rewards' const gwei = 1000000000n const uintSerializer = new UintNumberType(8) @@ -37,7 +34,7 @@ describe('EthVault - register', () => { const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' const deadline = VALIDATORS_DEADLINE - let admin: Signer, other: Wallet + let admin: Signer, other: Wallet, keysManager: Wallet let vault: EthVault, keeper: Keeper, validatorsRegistry: Contract let validatorsData: EthValidatorsData let validatorsRegistryRoot: string @@ -45,7 +42,7 @@ describe('EthVault - register', () => { let createVault: ThenArg>['createEthVault'] before('create fixture loader', async () => { - ;[admin, other] = (await (ethers as any).getSigners()).slice(1, 3) + ;[admin, other, keysManager] = (await (ethers as any).getSigners()).slice(1, 4) }) beforeEach('deploy fixture', async () => { @@ -64,17 +61,15 @@ describe('EthVault - register', () => { validatorsData = await createEthValidatorsData(vault) validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: validatorDeposit }) - await vault.connect(admin).setValidatorsRoot(validatorsData.root) + await vault.connect(admin).setKeysManager(keysManager.address) }) describe('single validator', () => { let validator: Buffer - let proof: string[] let approvalParams: IKeeperValidators.ApprovalParamsStruct beforeEach(async () => { validator = validatorsData.validators[0] - proof = getValidatorProof(validatorsData.tree, validator, 0) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] const signatures = getOraclesSignatures( await getEthValidatorsSigningData( @@ -96,55 +91,74 @@ describe('EthVault - register', () => { } }) + it('fails from non-keys manager', async () => { + await expect( + vault.connect(other).registerValidators(approvalParams) + ).to.be.revertedWithCustomError(vault, 'AccessDenied') + }) + it('fails with not enough withdrawable assets', async () => { await setBalance(await vault.getAddress(), ethers.parseEther('31.9')) - await expect(vault.registerValidator(approvalParams, proof)).to.be.revertedWithCustomError( - vault, - 'InsufficientAssets' - ) + await expect( + vault.connect(keysManager).registerValidators(approvalParams) + ).to.be.revertedWithCustomError(vault, 'InsufficientAssets') }) - it('fails with invalid proof', async () => { - const invalidProof = getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) + it('fails when not harvested', async () => { + // collateralize + const vaultReward = getHarvestParams(await vault.getAddress(), 1n, 0n) + const tree = await updateRewards(keeper, [vaultReward]) + const proof = tree.getProof([ + vaultReward.vault, + vaultReward.reward, + vaultReward.unlockedMevReward, + ]) + await vault.updateState({ + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + + // make vault not harvested + await updateRewards(keeper, [vaultReward]) + await updateRewards(keeper, [vaultReward]) await expect( - vault.registerValidator(approvalParams, invalidProof) - ).to.be.revertedWithCustomError(vault, 'InvalidProof') + vault.connect(keysManager).registerValidators(approvalParams) + ).to.be.revertedWithCustomError(vault, 'NotHarvested') }) it('fails with invalid validator length', async () => { const invalidValidator = appendDepositData( - validator, + Buffer.alloc(1), validatorDeposit, await vault.getAddress() ) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.registerValidator( - { - validatorsRegistryRoot, - validators: appendDepositData(validator, validatorDeposit, await vault.getAddress()), - deadline, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - invalidValidator, - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + validators: invalidValidator, + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + invalidValidator, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - proof - ) - ).to.be.revertedWithCustomError(vault, 'InvalidValidator') + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) + ).to.be.revertedWithCustomError(vault, 'InvalidValidators') }) it('succeeds', async () => { const index = await validatorsRegistry.get_deposit_count() - const receipt = await vault.registerValidator(approvalParams, proof) + const receipt = await vault.connect(keysManager).registerValidators(approvalParams) const publicKey = `0x${validator.subarray(0, 48).toString('hex')}` await expect(receipt).to.emit(vault, 'ValidatorRegistered').withArgs(publicKey) await expect(receipt) @@ -162,20 +176,13 @@ describe('EthVault - register', () => { describe('multiple validators', () => { let validators: Buffer[] - let indexes: number[] let approvalParams: IKeeperValidators.ApprovalParamsStruct - let multiProof: ValidatorsMultiProof let signatures: Buffer beforeEach(async () => { - multiProof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ - ...Array(validatorsData.validators.length).keys(), - ]) validators = validatorsData.validators const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] - const sortedVals = multiProof.leaves.map((v) => v[0]) const vaultAddr = await vault.getAddress() - indexes = validators.map((v) => sortedVals.indexOf(v)) const balance = validatorDeposit * BigInt(validators.length) + (await vault.totalExitingAssets()) + @@ -204,35 +211,30 @@ describe('EthVault - register', () => { it('fails with not enough withdrawable assets', async () => { await setBalance(await vault.getAddress(), validatorDeposit * BigInt(validators.length - 1)) await expect( - vault.registerValidators(approvalParams, indexes, multiProof.proofFlags, multiProof.proof) + vault.connect(keysManager).registerValidators(approvalParams) ).to.be.revertedWithCustomError(vault, 'InsufficientAssets') }) it('fails with invalid validators count', async () => { const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.registerValidators( - { - validatorsRegistryRoot, - validators: Buffer.from(''), - deadline, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - Buffer.from(''), - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + validators: Buffer.from(''), + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + Buffer.from(''), + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) ).to.be.revertedWithCustomError(vault, 'InvalidValidators') }) @@ -249,28 +251,23 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.registerValidators( - { - validatorsRegistryRoot, - deadline, - validators: invalidValidatorsConcat, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - invalidValidatorsConcat, - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + deadline, + validators: invalidValidatorsConcat, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + invalidValidatorsConcat, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) ).to.be.revertedWith( 'DepositContract: reconstructed DepositData does not match supplied deposit_data_root' ) @@ -288,28 +285,23 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.registerValidators( - { - validatorsRegistryRoot, - validators: invalidValidatorsConcat, - deadline, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - invalidValidatorsConcat, - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + validators: invalidValidatorsConcat, + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + invalidValidatorsConcat, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) ).to.be.revertedWith( 'DepositContract: reconstructed DepositData does not match supplied deposit_data_root' ) @@ -327,83 +319,28 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.registerValidators( - { - validatorsRegistryRoot, - validators: invalidValidatorsConcat, - deadline, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - invalidValidatorsConcat, - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + validators: invalidValidatorsConcat, + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + invalidValidatorsConcat, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) ).to.be.revertedWith( 'DepositContract: reconstructed DepositData does not match supplied deposit_data_root' ) }) - it('fails with invalid proof', async () => { - const invalidMultiProof = getValidatorsMultiProof( - validatorsData.tree, - validators.slice(1), - [...Array(validatorsData.validators.length).keys()].slice(1) - ) - - await expect( - vault.registerValidators( - approvalParams, - indexes, - invalidMultiProof.proofFlags, - invalidMultiProof.proof - ) - ).to.be.revertedWithCustomError(vault, 'MerkleProofInvalidMultiproof') - }) - - it('fails with invalid indexes', async () => { - await expect( - vault.registerValidators(approvalParams, [], multiProof.proofFlags, multiProof.proof) - ).to.be.revertedWithCustomError(vault, 'InvalidValidators') - - await expect( - vault.registerValidators( - approvalParams, - indexes.map((i) => i + 1), - multiProof.proofFlags, - multiProof.proof - ) - ).to.be.revertedWithPanic(PANIC_CODES.OUT_OF_BOUND_INDEX) - - await expect( - vault.registerValidators( - approvalParams, - indexes.slice(1), - multiProof.proofFlags, - multiProof.proof - ) - ).to.be.revertedWithCustomError(vault, 'InvalidValidators') - - await expect( - vault.registerValidators( - approvalParams, - indexes.sort(() => 0.5 - Math.random()), - multiProof.proofFlags, - multiProof.proof - ) - ).to.be.revertedWithCustomError(vault, 'InvalidProof') - }) - it('fails with invalid validator length', async () => { const invalidValidators = [ validators[0].subarray(0, 100), @@ -413,28 +350,23 @@ describe('EthVault - register', () => { for (let i = 0; i < invalidValidators.length; i++) { await expect( - vault.registerValidators( - { - validatorsRegistryRoot, - validators: invalidValidators[i], - deadline, - signatures: getOraclesSignatures( - await getEthValidatorsSigningData( - invalidValidators[i], - deadline, - exitSignaturesIpfsHash, - keeper, - vault, - validatorsRegistryRoot - ), - VALIDATORS_MIN_ORACLES + vault.connect(keysManager).registerValidators({ + validatorsRegistryRoot, + validators: invalidValidators[i], + deadline, + signatures: getOraclesSignatures( + await getEthValidatorsSigningData( + invalidValidators[i], + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot ), - exitSignaturesIpfsHash, - }, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + VALIDATORS_MIN_ORACLES + ), + exitSignaturesIpfsHash, + }) ).to.be.revertedWithCustomError(vault, 'InvalidValidators') } }) @@ -443,12 +375,7 @@ describe('EthVault - register', () => { const startIndex = uintSerializer.deserialize( ethers.getBytes(await validatorsRegistry.get_deposit_count()) ) - const receipt = await vault.registerValidators( - approvalParams, - indexes, - multiProof.proofFlags, - multiProof.proof - ) + const receipt = await vault.connect(keysManager).registerValidators(approvalParams) for (let i = 0; i < validators.length; i++) { const validator = validators[i] const publicKey = toHexString(validator.subarray(0, 48)) diff --git a/test/EthVault.settings.spec.ts b/test/EthVault.settings.spec.ts index 5dbd3a44..0b99e3a1 100644 --- a/test/EthVault.settings.spec.ts +++ b/test/EthVault.settings.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat' import { Contract, Wallet } from 'ethers' -import { EthVault, Keeper } from '../typechain-types' +import { EthVault, Keeper, DepositDataManager } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -17,7 +17,7 @@ describe('EthVault - settings', () => { let createVault: ThenArg>['createEthVault'] let admin: Wallet, keysManager: Wallet, other: Wallet, newFeeRecipient: Wallet - let keeper: Keeper, validatorsRegistry: Contract + let keeper: Keeper, validatorsRegistry: Contract, depositDataManager: DepositDataManager before('create fixture loader', async () => { ;[admin, keysManager, other, newFeeRecipient] = (await (ethers as any).getSigners()).slice(1, 5) @@ -27,6 +27,7 @@ describe('EthVault - settings', () => { ;({ keeper, validatorsRegistry, + depositDataManager, createEthVault: createVault, } = await loadFixture(ethVaultFixture)) }) @@ -58,39 +59,6 @@ describe('EthVault - settings', () => { }) }) - describe('validators root', () => { - const newValidatorsRoot = '0x059a8487a1ce461e9670c4646ef85164ae8791613866d28c972fb351dc45c606' - let vault: EthVault - - beforeEach('deploy vault', async () => { - vault = await createVault( - admin, - { - capacity, - feePercent, - metadataIpfsHash, - }, - false, - true - ) - await vault.connect(admin).setKeysManager(keysManager.address) - }) - - it('only keys manager can update', async () => { - await expect( - vault.connect(admin).setValidatorsRoot(newValidatorsRoot) - ).to.be.revertedWithCustomError(vault, 'AccessDenied') - }) - - it('can update', async () => { - const receipt = await vault.connect(keysManager).setValidatorsRoot(newValidatorsRoot) - await expect(receipt) - .to.emit(vault, 'ValidatorsRootUpdated') - .withArgs(keysManager.address, newValidatorsRoot) - await snapshotGasCost(receipt) - }) - }) - describe('keys manager', () => { let vault: EthVault @@ -113,16 +81,9 @@ describe('EthVault - settings', () => { ).to.be.revertedWithCustomError(vault, 'AccessDenied') }) - it('cannot set to zero address', async () => { - await expect(vault.connect(admin).setKeysManager(ZERO_ADDRESS)).to.be.revertedWithCustomError( - vault, - 'ZeroAddress' - ) - }) - it('can be updated by admin', async () => { // initially equals to admin - expect(await vault.keysManager()).to.be.eq(admin.address) + expect(await vault.keysManager()).to.be.eq(await depositDataManager.getAddress()) const receipt = await vault.connect(admin).setKeysManager(keysManager.address) await expect(receipt) .to.emit(vault, 'KeysManagerUpdated') @@ -146,7 +107,7 @@ describe('EthVault - settings', () => { false, true ) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) }) it('only admin can update', async () => { diff --git a/test/EthVault.state.spec.ts b/test/EthVault.state.spec.ts index a71881cc..fa059bc0 100644 --- a/test/EthVault.state.spec.ts +++ b/test/EthVault.state.spec.ts @@ -9,6 +9,7 @@ import { VaultsRegistry, OsTokenVaultController, OsTokenConfig, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -44,7 +45,8 @@ describe('EthVault - state', () => { validatorsRegistry: Contract, vaultsRegistry: VaultsRegistry, osTokenVaultController: OsTokenVaultController, - osTokenConfig: OsTokenConfig + osTokenConfig: OsTokenConfig, + depositDataManager: DepositDataManager let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] @@ -60,6 +62,7 @@ describe('EthVault - state', () => { vaultsRegistry, osTokenVaultController, osTokenConfig, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, { capacity, @@ -138,7 +141,7 @@ describe('EthVault - state', () => { ) const securityDeposit = 1000000000n await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: 1 }) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await vault._setTotalAssets(1) expect(await vault.totalAssets()).to.eq(1) expect(await vault.totalShares()).to.eq(securityDeposit + 1n) diff --git a/test/EthVault.upgrade.spec.ts b/test/EthVault.upgrade.spec.ts index 0a8fbfe1..a6092e06 100644 --- a/test/EthVault.upgrade.spec.ts +++ b/test/EthVault.upgrade.spec.ts @@ -11,6 +11,7 @@ import { OsTokenVaultController, SharedMevEscrow, VaultsRegistry, + DepositDataManager, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { @@ -50,6 +51,7 @@ describe('EthVault - upgrade', () => { sharedMevEscrow: SharedMevEscrow, osTokenConfig: OsTokenConfig, osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager, ethVaultFactory: EthVaultFactory, ethPrivVaultFactory: EthVaultFactory, ethErc20VaultFactory: EthVaultFactory, @@ -70,6 +72,7 @@ describe('EthVault - upgrade', () => { sharedMevEscrow = fixture.sharedMevEscrow osTokenConfig = fixture.osTokenConfig osTokenVaultController = fixture.osTokenVaultController + depositDataManager = fixture.depositDataManager ethVaultFactory = fixture.ethVaultFactory ethPrivVaultFactory = fixture.ethPrivVaultFactory ethErc20VaultFactory = fixture.ethErc20VaultFactory @@ -90,6 +93,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, + fixture.depositDataManager, EXITING_ASSETS_MIN_DELAY ) currImpl = await vault.implementation() @@ -139,6 +143,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, + fixture.depositDataManager, EXITING_ASSETS_MIN_DELAY ) callData = ethers.AbiCoder.defaultAbiCoder().encode(['uint128'], [100]) @@ -158,6 +163,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, + fixture.depositDataManager, EXITING_ASSETS_MIN_DELAY ) callData = ethers.AbiCoder.defaultAbiCoder().encode(['uint128'], [100]) @@ -265,12 +271,12 @@ describe('EthVault - upgrade', () => { const userShares = await vault.getShares(other.address) const userAssets = await vault.convertToAssets(userShares) const osTokenPosition = await vault.osTokenPositions(other.address) - const keysManager = await vault.keysManager() const mevEscrow = await vault.mevEscrow() const totalAssets = await vault.totalAssets() const totalShares = await vault.totalShares() const validatorIndex = await vault.validatorIndex() const validatorsRoot = await vault.validatorsRoot() + const vaultAddress = await vault.getAddress() expect(await vault.version()).to.be.eq(1) const receipt = await vault.connect(admin).upgradeToAndCall(newImpl, '0x') @@ -279,12 +285,12 @@ describe('EthVault - upgrade', () => { expect(await vault.getShares(other.address)).to.be.eq(userShares) expect(await vault.convertToAssets(userShares)).to.be.deep.eq(userAssets) expect(await vault.osTokenPositions(other.address)).to.be.above(osTokenPosition) - expect(await vault.keysManager()).to.be.eq(keysManager) + expect(await vault.keysManager()).to.be.eq(await depositDataManager.getAddress()) expect(await vault.mevEscrow()).to.be.eq(mevEscrow) expect(await vault.totalAssets()).to.be.eq(totalAssets) expect(await vault.totalShares()).to.be.eq(totalShares) - expect(await vault.validatorIndex()).to.be.eq(validatorIndex) - expect(await vault.validatorsRoot()).to.be.eq(validatorsRoot) + expect(await depositDataManager.depositDataIndexes(vaultAddress)).to.be.eq(validatorIndex) + expect(await depositDataManager.depositDataRoots(vaultAddress)).to.be.eq(validatorsRoot) await snapshotGasCost(receipt) } await checkVault(vaults[0], await ethVaultFactory.implementation()) diff --git a/test/EthVault.whitelist.spec.ts b/test/EthVault.whitelist.spec.ts index 9d7ac2be..98842a3a 100644 --- a/test/EthVault.whitelist.spec.ts +++ b/test/EthVault.whitelist.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthPrivVault, Keeper, IKeeperRewards } from '../typechain-types' +import { EthPrivVault, Keeper } from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -22,7 +22,10 @@ describe('EthVault - whitelist', () => { const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' let sender: Wallet, whitelister: Wallet, admin: Signer, other: Wallet - let vault: EthPrivVault, keeper: Keeper, validatorsRegistry: Contract + let vault: EthPrivVault, + keeper: Keeper, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let createPrivateVault: ThenArg>['createEthPrivVault'] @@ -35,6 +38,7 @@ describe('EthVault - whitelist', () => { createEthPrivVault: createPrivateVault, keeper, validatorsRegistry, + depositDataManager, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -114,7 +118,7 @@ describe('EthVault - whitelist', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) diff --git a/test/KeeperRewards.spec.ts b/test/KeeperRewards.spec.ts index b2e5f0f6..1764d33f 100644 --- a/test/KeeperRewards.spec.ts +++ b/test/KeeperRewards.spec.ts @@ -7,6 +7,7 @@ import { Keeper, OsTokenVaultController, SharedMevEscrow, + DepositDataManager, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' @@ -40,7 +41,8 @@ describe('KeeperRewards', () => { let keeper: Keeper, validatorsRegistry: Contract, sharedMevEscrow: SharedMevEscrow, - osTokenVaultController: OsTokenVaultController + osTokenVaultController: OsTokenVaultController, + depositDataManager: DepositDataManager let globalRewardsNonce: number beforeEach(async () => { @@ -51,6 +53,7 @@ describe('KeeperRewards', () => { validatorsRegistry, sharedMevEscrow, osTokenVaultController, + depositDataManager, } = await loadFixture(ethVaultFixture)) await setBalance(oracle.address, ethers.parseEther('10000')) }) @@ -290,7 +293,7 @@ describe('KeeperRewards', () => { await vault .connect(admin) .deposit(await admin.getAddress(), ZERO_ADDRESS, { value: validatorDeposit }) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) expect(await keeper.isCollateralized(await vault.getAddress())).to.equal(true) expect(await keeper.canHarvest(await vault.getAddress())).to.equal(false) @@ -416,13 +419,13 @@ describe('KeeperRewards', () => { it('fails for invalid reward', async () => { await expect( ownMevVault.updateState({ ...harvestParams, reward: 0 }) - ).to.be.revertedWithCustomError(ownMevVault, 'InvalidProof') + ).to.be.revertedWithCustomError(keeper, 'InvalidProof') }) it('fails for invalid proof', async () => { await expect( ownMevVault.updateState({ ...harvestParams, proof: [] }) - ).to.be.revertedWithCustomError(ownMevVault, 'InvalidProof') + ).to.be.revertedWithCustomError(keeper, 'InvalidProof') }) it('fails for invalid root', async () => { @@ -664,13 +667,13 @@ describe('KeeperRewards', () => { it('fails for invalid unlocked MEV reward', async () => { await expect( sharedMevVault.updateState({ ...harvestParams, unlockedMevReward: 0n }) - ).to.be.revertedWithCustomError(sharedMevVault, 'InvalidProof') + ).to.be.revertedWithCustomError(keeper, 'InvalidProof') }) it('fails for invalid proof', async () => { await expect( sharedMevVault.updateState({ ...harvestParams, proof: [] }) - ).to.be.revertedWithCustomError(sharedMevVault, 'InvalidProof') + ).to.be.revertedWithCustomError(keeper, 'InvalidProof') }) it('fails for invalid root', async () => { diff --git a/test/KeeperValidators.spec.ts b/test/KeeperValidators.spec.ts index 883daafc..76ffd8e8 100644 --- a/test/KeeperValidators.spec.ts +++ b/test/KeeperValidators.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat' import { Contract, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, IKeeperValidators, Keeper } from '../typechain-types' +import { EthVault, IKeeperValidators, Keeper, DepositDataManager } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { expect } from './shared/expect' @@ -10,6 +10,7 @@ import { VALIDATORS_DEADLINE, VALIDATORS_MIN_ORACLES, ZERO_ADDRESS, + ZERO_BYTES32, } from './shared/constants' import { createEthValidatorsData, @@ -37,7 +38,10 @@ describe('KeeperValidators', () => { let createVault: ThenArg>['createEthVault'] let sender: Wallet, dao: Wallet, admin: Wallet - let keeper: Keeper, vault: EthVault, validatorsRegistry: Contract + let keeper: Keeper, + vault: EthVault, + validatorsRegistry: Contract, + depositDataManager: DepositDataManager let validatorsData: EthValidatorsData let validatorsRegistryRoot: string @@ -46,6 +50,7 @@ describe('KeeperValidators', () => { ;({ keeper, validatorsRegistry, + depositDataManager, createEthVault: createVault, } = await loadFixture(ethVaultFixture)) vault = await createVault( @@ -60,7 +65,9 @@ describe('KeeperValidators', () => { ) validatorsData = await createEthValidatorsData(vault) validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() - await vault.connect(admin).setValidatorsRoot(validatorsData.root) + await depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), validatorsData.root) }) describe('register single validator', () => { @@ -106,15 +113,15 @@ describe('KeeperValidators', () => { validator.subarray(144, 176), { value: depositAmount } ) - await expect(vault.registerValidator(approveParams, proof)).revertedWithCustomError( - keeper, - 'InvalidValidatorsRegistryRoot' - ) + await expect( + depositDataManager.registerValidator(await vault.getAddress(), approveParams, proof) + ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') }) it('fails for invalid signatures', async () => { await expect( - vault.registerValidator( + depositDataManager.registerValidator( + await vault.getAddress(), { ...approveParams, signatures: getOraclesSignatures(signingData, VALIDATORS_MIN_ORACLES - 1), @@ -126,7 +133,8 @@ describe('KeeperValidators', () => { it('fails for invalid deadline', async () => { await expect( - vault.registerValidator( + depositDataManager.registerValidator( + await vault.getAddress(), { ...approveParams, deadline: deadline + 1n, @@ -138,7 +146,8 @@ describe('KeeperValidators', () => { it('fails for expired deadline', async () => { await expect( - vault.registerValidator( + depositDataManager.registerValidator( + await vault.getAddress(), { ...approveParams, deadline: await getLatestBlockTimestamp(), @@ -150,7 +159,8 @@ describe('KeeperValidators', () => { it('fails for invalid validator', async () => { await expect( - vault.registerValidator( + depositDataManager.registerValidator( + await vault.getAddress(), { ...approveParams, validators: validatorsData.validators[1], @@ -162,7 +172,8 @@ describe('KeeperValidators', () => { it('fails for invalid proof', async () => { await expect( - vault.registerValidator( + depositDataManager.registerValidator( + await vault.getAddress(), approveParams, getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) ) @@ -175,7 +186,11 @@ describe('KeeperValidators', () => { expect(rewards.assets).to.eq(0) const globalRewardsNonce = await keeper.rewardsNonce() - let receipt = await vault.registerValidator(approveParams, proof) + let receipt = await depositDataManager.registerValidator( + await vault.getAddress(), + approveParams, + proof + ) await expect(receipt) .to.emit(keeper, 'ValidatorsApproval') .withArgs(await vault.getAddress(), approveParams.exitSignaturesIpfsHash) @@ -190,10 +205,9 @@ describe('KeeperValidators', () => { const newValidatorsRegistryRoot = await validatorsRegistry.get_deposit_root() // fails to register twice - await expect(vault.registerValidator(approveParams, proof)).revertedWithCustomError( - keeper, - 'InvalidValidatorsRegistryRoot' - ) + await expect( + depositDataManager.registerValidator(await vault.getAddress(), approveParams, proof) + ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') const newValidator = validatorsData.validators[1] const newExitSignatureIpfsHash = exitSignatureIpfsHashes[1] @@ -209,7 +223,8 @@ describe('KeeperValidators', () => { newValidatorsRegistryRoot ) const newSignatures = getOraclesSignatures(newSigningData, ORACLES.length) - receipt = await vault.registerValidator( + receipt = await depositDataManager.registerValidator( + await vault.getAddress(), { validatorsRegistryRoot: newValidatorsRegistryRoot, validators: newValidator, @@ -282,13 +297,20 @@ describe('KeeperValidators', () => { { value: depositAmount } ) await expect( - vault.registerValidators(approveParams, indexes, proof.proofFlags, proof.proof) + depositDataManager.registerValidators( + await vault.getAddress(), + approveParams, + indexes, + proof.proofFlags, + proof.proof + ) ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') }) it('fails for invalid signatures', async () => { await expect( - vault.registerValidators( + depositDataManager.registerValidators( + await vault.getAddress(), { ...approveParams, signatures: getOraclesSignatures(signingData, VALIDATORS_MIN_ORACLES - 1), @@ -302,7 +324,8 @@ describe('KeeperValidators', () => { it('fails for invalid validators', async () => { await expect( - vault.registerValidators( + depositDataManager.registerValidators( + await vault.getAddress(), { ...approveParams, validators: validators[0], @@ -316,7 +339,8 @@ describe('KeeperValidators', () => { it('fails for invalid deadline', async () => { await expect( - vault.registerValidators( + depositDataManager.registerValidators( + await vault.getAddress(), { ...approveParams, deadline: deadline + 1n, @@ -330,7 +354,8 @@ describe('KeeperValidators', () => { it('fails for expired deadline', async () => { await expect( - vault.registerValidators( + depositDataManager.registerValidators( + await vault.getAddress(), { ...approveParams, deadline: await getLatestBlockTimestamp(), @@ -346,7 +371,8 @@ describe('KeeperValidators', () => { const invalidProof = getValidatorsMultiProof(validatorsData.tree, [validators[0]], [0]) const exitSignaturesIpfsHash = approveParams.exitSignaturesIpfsHash as string await expect( - vault.registerValidators( + depositDataManager.registerValidators( + await vault.getAddress(), { validatorsRegistryRoot, deadline, @@ -378,7 +404,8 @@ describe('KeeperValidators', () => { const validatorsConcat = Buffer.concat(validators) const globalRewardsNonce = await keeper.rewardsNonce() - let receipt = await vault.registerValidators( + let receipt = await depositDataManager.registerValidators( + await vault.getAddress(), approveParams, indexes, proof.proofFlags, @@ -398,7 +425,13 @@ describe('KeeperValidators', () => { // fails to register twice await expect( - vault.registerValidators(approveParams, indexes, proof.proofFlags, proof.proof) + depositDataManager.registerValidators( + await vault.getAddress(), + approveParams, + indexes, + proof.proofFlags, + proof.proof + ) ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') await vault @@ -406,7 +439,12 @@ describe('KeeperValidators', () => { .deposit(sender.address, referrer, { value: depositAmount * BigInt(validators.length) }) // reset validator index - await vault.connect(admin).setValidatorsRoot(validatorsData.root) + await depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), ZERO_BYTES32) + await depositDataManager + .connect(admin) + .setDepositDataRoot(await vault.getAddress(), validatorsData.root) const newSigningData = await getEthValidatorsSigningData( validatorsConcat, deadline, @@ -416,7 +454,8 @@ describe('KeeperValidators', () => { newValidatorsRegistryRoot ) const newSignatures = getOraclesSignatures(newSigningData, ORACLES.length) - receipt = await vault.registerValidators( + receipt = await depositDataManager.registerValidators( + await vault.getAddress(), { validatorsRegistryRoot: newValidatorsRegistryRoot, deadline, @@ -480,7 +519,7 @@ describe('KeeperValidators', () => { }) it('fails for invalid signatures', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await expect( keeper.updateExitSignatures( await vault.getAddress(), @@ -492,7 +531,7 @@ describe('KeeperValidators', () => { }) it('fails for invalid deadline', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await expect( keeper.updateExitSignatures( await vault.getAddress(), @@ -504,7 +543,7 @@ describe('KeeperValidators', () => { }) it('fails for expired deadline', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const newDeadline = await getLatestBlockTimestamp() const newSigningData = await getEthValidatorsExitSignaturesSigningData( keeper, @@ -524,7 +563,7 @@ describe('KeeperValidators', () => { }) it('fails to submit update twice', async () => { - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) await keeper.updateExitSignatures( await vault.getAddress(), deadline, @@ -546,7 +585,7 @@ describe('KeeperValidators', () => { const nonce = await keeper.exitSignaturesNonces(await vault.getAddress()) expect(nonce).to.eq(0) - await collateralizeEthVault(vault, keeper, validatorsRegistry, admin) + await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) const receipt = await keeper .connect(sender) diff --git a/test/OsToken.spec.ts b/test/OsToken.spec.ts index 7733a312..c568243f 100644 --- a/test/OsToken.spec.ts +++ b/test/OsToken.spec.ts @@ -1,7 +1,13 @@ import { ethers, network } from 'hardhat' import { Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { OsTokenVaultController, OsToken, EthVault, Keeper } from '../typechain-types' +import { + OsTokenVaultController, + OsToken, + EthVault, + Keeper, + DepositDataManager, +} from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -31,7 +37,8 @@ describe('OsToken', () => { let osTokenVaultController: OsTokenVaultController, osToken: OsToken, vault: EthVault, - keeper: Keeper + keeper: Keeper, + depositDataManager: DepositDataManager before('create fixture loader', async () => { ;[dao, initialHolder, admin, spender, recipient] = await (ethers as any).getSigners() @@ -47,11 +54,19 @@ describe('OsToken', () => { osTokenVaultController = fixture.osTokenVaultController keeper = fixture.keeper osToken = fixture.osToken + depositDataManager = fixture.depositDataManager + vault = await fixture.createEthVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) // collateralize vault - await collateralizeEthVault(vault, fixture.keeper, fixture.validatorsRegistry, admin) + await collateralizeEthVault( + vault, + fixture.keeper, + depositDataManager, + admin, + fixture.validatorsRegistry + ) await vault .connect(initialHolder) .deposit(initialHolder.address, ZERO_ADDRESS, { value: assets }) diff --git a/test/PriceFeed.test.ts b/test/PriceFeed.test.ts index aed76aee..bda6a6fb 100644 --- a/test/PriceFeed.test.ts +++ b/test/PriceFeed.test.ts @@ -1,7 +1,13 @@ import { ethers } from 'hardhat' import { Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, IKeeperRewards, OsTokenVaultController, PriceFeed } from '../typechain-types' +import { + EthVault, + IKeeperRewards, + OsTokenVaultController, + PriceFeed, + DepositDataManager, +} from '../typechain-types' import { expect } from './shared/expect' import { createPriceFeed, ethVaultFixture } from './shared/fixtures' import { ONE_DAY, ZERO_ADDRESS } from './shared/constants' @@ -25,7 +31,10 @@ describe('PriceFeed', () => { metadataIpfsHash: 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u', } let sender: Wallet, admin: Signer, dao: Wallet - let osTokenVaultController: OsTokenVaultController, priceFeed: PriceFeed, vault: EthVault + let osTokenVaultController: OsTokenVaultController, + priceFeed: PriceFeed, + vault: EthVault, + depositDataManager: DepositDataManager before('create fixture loader', async () => { ;[sender, dao, admin] = await (ethers as any).getSigners() @@ -37,10 +46,17 @@ describe('PriceFeed', () => { admin = await ethers.getImpersonatedSigner(await vault.admin()) osTokenVaultController = fixture.osTokenVaultController + depositDataManager = fixture.depositDataManager priceFeed = await createPriceFeed(osTokenVaultController, description) // collateralize vault - await collateralizeEthVault(vault, fixture.keeper, fixture.validatorsRegistry, admin) + await collateralizeEthVault( + vault, + fixture.keeper, + depositDataManager, + admin, + fixture.validatorsRegistry + ) await vault.connect(sender).deposit(sender.address, ZERO_ADDRESS, { value: shares }) const reward = ethers.parseEther('1') diff --git a/test/RewardSplitter.spec.ts b/test/RewardSplitter.spec.ts index 91e508c6..44b72ca2 100644 --- a/test/RewardSplitter.spec.ts +++ b/test/RewardSplitter.spec.ts @@ -7,6 +7,7 @@ import { Keeper, RewardSplitter, RewardSplitter__factory, + DepositDataManager, } from '../typechain-types' import { createRewardSplitterFactory, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -16,7 +17,11 @@ import snapshotGasCost from './shared/snapshotGasCost' describe('RewardSplitter', () => { let admin: Wallet, other: Wallet - let vault: EthVault, keeper: Keeper, rewardSplitter: RewardSplitter, erc20Vault: EthErc20Vault + let vault: EthVault, + keeper: Keeper, + rewardSplitter: RewardSplitter, + erc20Vault: EthErc20Vault, + depositDataManager: DepositDataManager before('create fixture loader', async () => { ;[admin, other] = (await (ethers as any).getSigners()).slice(1, 3) @@ -47,8 +52,21 @@ describe('RewardSplitter', () => { true ) keeper = fixture.keeper - await collateralizeEthVault(vault, keeper, fixture.validatorsRegistry, admin) - await collateralizeEthVault(erc20Vault, keeper, fixture.validatorsRegistry, admin) + depositDataManager = fixture.depositDataManager + await collateralizeEthVault( + vault, + keeper, + depositDataManager, + admin, + fixture.validatorsRegistry + ) + await collateralizeEthVault( + erc20Vault, + keeper, + depositDataManager, + admin, + fixture.validatorsRegistry + ) const rewardSplitterFactory = await createRewardSplitterFactory() const rewardSplitterAddress = await rewardSplitterFactory diff --git a/test/VaultsRegistry.spec.ts b/test/VaultsRegistry.spec.ts index 7cb92792..cb96788f 100644 --- a/test/VaultsRegistry.spec.ts +++ b/test/VaultsRegistry.spec.ts @@ -39,6 +39,7 @@ describe('VaultsRegistry', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, + fixture.depositDataManager, EXITING_ASSETS_MIN_DELAY ) }) diff --git a/test/__snapshots__/DepositDataManager.spec.ts.snap b/test/__snapshots__/DepositDataManager.spec.ts.snap new file mode 100644 index 00000000..9a5db4bd --- /dev/null +++ b/test/__snapshots__/DepositDataManager.spec.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DepositDataManager deposit data manager update succeeds 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 62126, +} +`; + +exports[`DepositDataManager deposit data root update success 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 56000, +} +`; + +exports[`DepositDataManager migrate succeeds 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 118756, +} +`; + +exports[`DepositDataManager multiple validators succeeds 1`] = ` +Object { + "calldataByteLength": 3364, + "gasUsed": 684817, +} +`; + +exports[`DepositDataManager single validator succeeds 1`] = ` +Object { + "calldataByteLength": 1156, + "gasUsed": 331930, +} +`; diff --git a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap index 1180d9c3..c90ab2e7 100644 --- a/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71181, + "gasUsed": 71093, } `; @@ -17,13 +17,13 @@ Object { exports[`EthBlocklistErc20Vault mint osToken can mint from not blocked user 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 174071, + "gasUsed": 174049, } `; exports[`EthBlocklistErc20Vault transfer can transfer 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 58987, + "gasUsed": 58921, } `; diff --git a/test/__snapshots__/EthBlocklistVault.spec.ts.snap b/test/__snapshots__/EthBlocklistVault.spec.ts.snap index f422fa1e..7f5e8ce5 100644 --- a/test/__snapshots__/EthBlocklistVault.spec.ts.snap +++ b/test/__snapshots__/EthBlocklistVault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthBlocklistVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69056, + "gasUsed": 68968, } `; @@ -17,6 +17,6 @@ Object { exports[`EthBlocklistVault mint osToken can mint from not blocked user 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 173861, + "gasUsed": 173839, } `; diff --git a/test/__snapshots__/EthErc20Vault.spec.ts.snap b/test/__snapshots__/EthErc20Vault.spec.ts.snap index e4386f4c..06d196d5 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthErc20Vault deposit emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68858, + "gasUsed": 68776, } `; exports[`EthErc20Vault deposit through receive fallback function emits transfer event 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 76116, + "gasUsed": 76122, } `; exports[`EthErc20Vault enter exit queue emits transfer event 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 96285, + "gasUsed": 96269, } `; diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index a4d88765..14afb38c 100644 --- a/test/__snapshots__/EthFoxVault.spec.ts.snap +++ b/test/__snapshots__/EthFoxVault.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthFoxVault blocklist can be updated by blocklist manager 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 53743, + "gasUsed": 53677, } `; exports[`EthFoxVault blocklist can be updated by blocklist manager 2`] = ` Object { "calldataByteLength": 68, - "gasUsed": 31831, + "gasUsed": 31765, } `; exports[`EthFoxVault deposit can be called by not blocked user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 68968, + "gasUsed": 68880, } `; @@ -31,20 +31,20 @@ Object { exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for collateralized vault 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 119659, + "gasUsed": 119593, } `; exports[`EthFoxVault ejecting user does not fail for user with no vault shares 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 55791, + "gasUsed": 55725, } `; exports[`EthFoxVault set blocklist manager admin can update blocklist manager 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 35941, + "gasUsed": 35897, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 51309ab0..f54b1e17 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -3,62 +3,62 @@ exports[`EthGenesisVault can deposit through receive fallback function 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 74328, + "gasUsed": 74334, } `; exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79638, + "gasUsed": 79584, } `; exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 77206, + "gasUsed": 77160, } `; exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { - "calldataByteLength": 3716, - "gasUsed": 638183, + "calldataByteLength": 3748, + "gasUsed": 649263, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { - "calldataByteLength": 1124, - "gasUsed": 301781, + "calldataByteLength": 1156, + "gasUsed": 310166, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150242, + "gasUsed": 150251, } `; exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 145811, + "gasUsed": 145820, } `; exports[`EthGenesisVault update state splits penalty between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 119650, + "gasUsed": 119659, } `; exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167342, + "gasUsed": 167351, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index d005196a..0a21bcd2 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71169, + "gasUsed": 71081, } `; @@ -17,13 +17,13 @@ Object { exports[`EthPrivErc20Vault mint osToken can mint from whitelisted user 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 174096, + "gasUsed": 174074, } `; exports[`EthPrivErc20Vault transfer can transfer to whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 59015, + "gasUsed": 58949, } `; diff --git a/test/__snapshots__/EthPrivVault.spec.ts.snap b/test/__snapshots__/EthPrivVault.spec.ts.snap index ebdedaf3..60554a49 100644 --- a/test/__snapshots__/EthPrivVault.spec.ts.snap +++ b/test/__snapshots__/EthPrivVault.spec.ts.snap @@ -3,6 +3,6 @@ exports[`EthPrivVault mint osToken can mint from not whitelisted user 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 173886, + "gasUsed": 173864, } `; diff --git a/test/__snapshots__/EthVault.deposit.spec.ts.snap b/test/__snapshots__/EthVault.deposit.spec.ts.snap index 6858829e..188c129d 100644 --- a/test/__snapshots__/EthVault.deposit.spec.ts.snap +++ b/test/__snapshots__/EthVault.deposit.spec.ts.snap @@ -3,27 +3,27 @@ exports[`EthVault - deposit empty vault: no assets & no shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66733, + "gasUsed": 66651, } `; exports[`EthVault - deposit full vault: assets & shares deposit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 66733, + "gasUsed": 66651, } `; exports[`EthVault - deposit full vault: assets & shares deposit through receive fallback function 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 74288, + "gasUsed": 74294, } `; exports[`EthVault - deposit full vault: assets & shares update state and deposit 1`] = ` Object { "calldataByteLength": 260, - "gasUsed": 155321, + "gasUsed": 155308, } `; diff --git a/test/__snapshots__/EthVault.liquidate.spec.ts.snap b/test/__snapshots__/EthVault.liquidate.spec.ts.snap index cbe7a222..bc58a4e7 100644 --- a/test/__snapshots__/EthVault.liquidate.spec.ts.snap +++ b/test/__snapshots__/EthVault.liquidate.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - liquidate calculates liquidation correctly 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 109382, + "gasUsed": 109388, } `; exports[`EthVault - liquidate can liquidate 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 109382, + "gasUsed": 109388, } `; diff --git a/test/__snapshots__/EthVault.mint.spec.ts.snap b/test/__snapshots__/EthVault.mint.spec.ts.snap index c3972025..a2151efe 100644 --- a/test/__snapshots__/EthVault.mint.spec.ts.snap +++ b/test/__snapshots__/EthVault.mint.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - mint mints osTokens to the receiver 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 171574, + "gasUsed": 171564, } `; exports[`EthVault - mint updates position accumulated fee 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 116686, + "gasUsed": 116676, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index cd9430e5..4f7d0e4e 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168451, + "gasUsed": 168343, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 109844, + "gasUsed": 109728, } `; diff --git a/test/__snapshots__/EthVault.redeem.spec.ts.snap b/test/__snapshots__/EthVault.redeem.spec.ts.snap index 5390f7e7..7c7e5c0f 100644 --- a/test/__snapshots__/EthVault.redeem.spec.ts.snap +++ b/test/__snapshots__/EthVault.redeem.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - redeem osToken calculates redeem correctly 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 125543, + "gasUsed": 125549, } `; exports[`EthVault - redeem osToken can redeem 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 125543, + "gasUsed": 125549, } `; diff --git a/test/__snapshots__/EthVault.register.spec.ts.snap b/test/__snapshots__/EthVault.register.spec.ts.snap index 18bd2761..ca7d4fab 100644 --- a/test/__snapshots__/EthVault.register.spec.ts.snap +++ b/test/__snapshots__/EthVault.register.spec.ts.snap @@ -2,14 +2,14 @@ exports[`EthVault - register multiple validators succeeds 1`] = ` Object { - "calldataByteLength": 3332, - "gasUsed": 673669, + "calldataByteLength": 2532, + "gasUsed": 630912, } `; exports[`EthVault - register single validator succeeds 1`] = ` Object { - "calldataByteLength": 1156, - "gasUsed": 324148, + "calldataByteLength": 964, + "gasUsed": 298127, } `; diff --git a/test/__snapshots__/EthVault.settings.spec.ts.snap b/test/__snapshots__/EthVault.settings.spec.ts.snap index 35a28b8d..68ee11d3 100644 --- a/test/__snapshots__/EthVault.settings.spec.ts.snap +++ b/test/__snapshots__/EthVault.settings.spec.ts.snap @@ -3,27 +3,20 @@ exports[`EthVault - settings fee recipient can update 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 44014, + "gasUsed": 43976, } `; exports[`EthVault - settings keys manager can be updated by admin 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 52980, + "gasUsed": 52907, } `; exports[`EthVault - settings metadata IPFS hash only admin can update 1`] = ` Object { "calldataByteLength": 132, - "gasUsed": 32625, -} -`; - -exports[`EthVault - settings validators root can update 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 54908, + "gasUsed": 32559, } `; diff --git a/test/__snapshots__/EthVault.state.spec.ts.snap b/test/__snapshots__/EthVault.state.spec.ts.snap index 6f1db2a9..8dbcf11a 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -3,21 +3,21 @@ exports[`EthVault - state allocates fee to recipient when delta is above zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117553, + "gasUsed": 117534, } `; exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117338, + "gasUsed": 117319, } `; exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 107117, + "gasUsed": 107120, } `; diff --git a/test/__snapshots__/EthVault.token.spec.ts.snap b/test/__snapshots__/EthVault.token.spec.ts.snap index 29a129bd..09221db7 100644 --- a/test/__snapshots__/EthVault.token.spec.ts.snap +++ b/test/__snapshots__/EthVault.token.spec.ts.snap @@ -17,7 +17,7 @@ Object { exports[`EthVault - token permit accepts owner signature 1`] = ` Object { "calldataByteLength": 228, - "gasUsed": 82389, + "gasUsed": 82357, } `; @@ -38,13 +38,13 @@ Object { exports[`EthVault - token transfer when the sender transfers all balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 54465, + "gasUsed": 54399, } `; exports[`EthVault - token transfer when the sender transfers zero tokens transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 36541, + "gasUsed": 36475, } `; diff --git a/test/__snapshots__/EthVault.upgrade.spec.ts.snap b/test/__snapshots__/EthVault.upgrade.spec.ts.snap index 7750f50b..f254c3ce 100644 --- a/test/__snapshots__/EthVault.upgrade.spec.ts.snap +++ b/test/__snapshots__/EthVault.upgrade.spec.ts.snap @@ -3,48 +3,48 @@ exports[`EthVault - upgrade does not modify the state variables 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 82702, + "gasUsed": 162871, } `; exports[`EthVault - upgrade does not modify the state variables 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 83366, + "gasUsed": 163547, } `; exports[`EthVault - upgrade does not modify the state variables 3`] = ` Object { "calldataByteLength": 100, - "gasUsed": 82922, + "gasUsed": 163103, } `; exports[`EthVault - upgrade does not modify the state variables 4`] = ` Object { "calldataByteLength": 100, - "gasUsed": 83586, + "gasUsed": 163767, } `; exports[`EthVault - upgrade does not modify the state variables 5`] = ` Object { "calldataByteLength": 100, - "gasUsed": 82790, + "gasUsed": 162945, } `; exports[`EthVault - upgrade works with valid call data 1`] = ` Object { "calldataByteLength": 132, - "gasUsed": 76084, + "gasUsed": 76046, } `; exports[`EthVault - upgrade works with valid call data 2`] = ` Object { "calldataByteLength": 132, - "gasUsed": 76084, + "gasUsed": 76046, } `; diff --git a/test/__snapshots__/EthVault.whitelist.spec.ts.snap b/test/__snapshots__/EthVault.whitelist.spec.ts.snap index 0fff6a6c..dce0e713 100644 --- a/test/__snapshots__/EthVault.whitelist.spec.ts.snap +++ b/test/__snapshots__/EthVault.whitelist.spec.ts.snap @@ -3,7 +3,7 @@ exports[`EthVault - whitelist deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 69044, + "gasUsed": 68956, } `; @@ -17,7 +17,7 @@ Object { exports[`EthVault - whitelist set whitelister admin can update whitelister 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 36223, + "gasUsed": 36135, } `; diff --git a/test/__snapshots__/EthVault.withdraw.spec.ts.snap b/test/__snapshots__/EthVault.withdraw.spec.ts.snap index 9f11d9f4..4561b60a 100644 --- a/test/__snapshots__/EthVault.withdraw.spec.ts.snap +++ b/test/__snapshots__/EthVault.withdraw.spec.ts.snap @@ -3,35 +3,35 @@ exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 76025, + "gasUsed": 75973, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48843, + "gasUsed": 48801, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in single transaction 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 51461, + "gasUsed": 51409, } `; exports[`EthVault - withdraw claim exited assets for single user in single checkpoint 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48843, + "gasUsed": 48801, } `; exports[`EthVault - withdraw enter exit queue locks assets for the time of exit 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 77382, + "gasUsed": 77366, } `; diff --git a/test/__snapshots__/EthVaultFactory.spec.ts.snap b/test/__snapshots__/EthVaultFactory.spec.ts.snap index 406947fa..68bd70d0 100644 --- a/test/__snapshots__/EthVaultFactory.spec.ts.snap +++ b/test/__snapshots__/EthVaultFactory.spec.ts.snap @@ -17,14 +17,14 @@ Object { exports[`EthVaultFactory EthErc20Vault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 553267, + "gasUsed": 553279, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 404448, + "gasUsed": 404460, } `; @@ -45,13 +45,13 @@ Object { exports[`EthVaultFactory EthVault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 479145, + "gasUsed": 479157, } `; exports[`EthVaultFactory EthVault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 330326, + "gasUsed": 330338, } `; diff --git a/test/__snapshots__/KeeperRewards.spec.ts.snap b/test/__snapshots__/KeeperRewards.spec.ts.snap index 84165ae3..1e20d73d 100644 --- a/test/__snapshots__/KeeperRewards.spec.ts.snap +++ b/test/__snapshots__/KeeperRewards.spec.ts.snap @@ -2,43 +2,43 @@ exports[`KeeperRewards harvest (own escrow) succeeds for latest rewards root 1`] = ` Object { - "calldataByteLength": 324, - "gasUsed": 111374, + "calldataByteLength": 292, + "gasUsed": 110652, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 1`] = ` Object { - "calldataByteLength": 324, - "gasUsed": 113528, + "calldataByteLength": 292, + "gasUsed": 112806, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 74295, + "gasUsed": 74286, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for latest rewards root 1`] = ` Object { - "calldataByteLength": 292, - "gasUsed": 143928, + "calldataByteLength": 324, + "gasUsed": 144655, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 1`] = ` Object { - "calldataByteLength": 292, - "gasUsed": 146082, + "calldataByteLength": 324, + "gasUsed": 146809, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 90462, + "gasUsed": 90443, } `; @@ -59,13 +59,13 @@ Object { exports[`KeeperRewards update rewards succeeds 2`] = ` Object { "calldataByteLength": 772, - "gasUsed": 123627, + "gasUsed": 123639, } `; exports[`KeeperRewards update rewards succeeds with all signatures 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 146931, + "gasUsed": 146943, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index 426a2016..45dd8b5d 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -2,29 +2,29 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { - "calldataByteLength": 3716, - "gasUsed": 679986, + "calldataByteLength": 3748, + "gasUsed": 691222, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { - "calldataByteLength": 3716, - "gasUsed": 588392, + "calldataByteLength": 3748, + "gasUsed": 599466, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 330512, + "gasUsed": 338356, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { - "calldataByteLength": 1508, - "gasUsed": 276240, + "calldataByteLength": 1540, + "gasUsed": 284631, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index f2cc9f02..75364a22 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -3,7 +3,7 @@ exports[`RewardSplitter decrease shares owner can decrease shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 67101, + "gasUsed": 67019, } `; @@ -17,20 +17,20 @@ Object { exports[`RewardSplitter sync rewards anyone can sync rewards 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 73126, + "gasUsed": 73044, } `; exports[`RewardSplitter withdraw rewards can claim vault tokens for ERC-20 vault 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78180, + "gasUsed": 78114, } `; exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170884, + "gasUsed": 170789, } `; diff --git a/test/__snapshots__/VaultsRegistry.spec.ts.snap b/test/__snapshots__/VaultsRegistry.spec.ts.snap index da8cf135..ab82aafd 100644 --- a/test/__snapshots__/VaultsRegistry.spec.ts.snap +++ b/test/__snapshots__/VaultsRegistry.spec.ts.snap @@ -3,7 +3,7 @@ exports[`VaultsRegistry factory can add vault 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 330326, + "gasUsed": 330338, } `; diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index d76c3751..39da306b 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -51,6 +51,8 @@ import { SharedMevEscrow__factory, VaultsRegistry, VaultsRegistry__factory, + DepositDataManager, + DepositDataManager__factory, } from '../../typechain-types' import { getEthValidatorsRegistryFactory } from './contracts' import { @@ -239,6 +241,15 @@ export const createRewardSplitterFactory = async function (): Promise { + const signer = await ethers.provider.getSigner() + const factory = await ethers.getContractFactory('DepositDataManager') + const contract = await factory.deploy(await vaultsRegistry.getAddress()) + return DepositDataManager__factory.connect(await contract.getAddress(), signer) +} + export const createOsTokenVaultController = async function ( keeperAddress: string, registry: VaultsRegistry, @@ -399,6 +410,7 @@ export const deployEthGenesisVaultImpl = async function ( osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, + depositDataManager: DepositDataManager, poolEscrow: PoolEscrowMock, rewardEthToken: LegacyRewardTokenMock ): Promise { @@ -410,6 +422,7 @@ export const deployEthGenesisVaultImpl = async function ( await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), + await depositDataManager.getAddress(), await poolEscrow.getAddress(), await rewardEthToken.getAddress(), EXITING_ASSETS_MIN_DELAY, @@ -428,6 +441,7 @@ export const deployEthVaultImplementation = async function ( osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, + depositDataManager: DepositDataManager, exitingAssetsMinDelay: number ): Promise { const factory = await ethers.getContractFactory(vaultType) @@ -438,6 +452,7 @@ export const deployEthVaultImplementation = async function ( await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), + await depositDataManager.getAddress(), exitingAssetsMinDelay, ] const contract = await factory.deploy(...constructorArgs) @@ -540,6 +555,7 @@ interface EthVaultFixture { vaultsRegistry: VaultsRegistry keeper: Keeper sharedMevEscrow: SharedMevEscrow + depositDataManager: DepositDataManager validatorsRegistry: Contract ethVaultFactory: EthVaultFactory ethPrivVaultFactory: EthVaultFactory @@ -672,7 +688,10 @@ export const ethVaultFixture = async function (): Promise { OSTOKEN_LTV ) - // 7. deploy implementations and factories + // 7. deploy depositDataManager + const depositDataManager = await createDepositDataManager(vaultsRegistry) + + // 8. deploy implementations and factories const factories = {} const implementations = {} @@ -693,6 +712,7 @@ export const ethVaultFixture = async function (): Promise { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, EXITING_ASSETS_MIN_DELAY ) await vaultsRegistry.addVaultImpl(vaultImpl) @@ -717,6 +737,7 @@ export const ethVaultFixture = async function (): Promise { return { vaultsRegistry, sharedMevEscrow, + depositDataManager, keeper, validatorsRegistry, ethVaultFactory, @@ -764,6 +785,7 @@ export const ethVaultFixture = async function (): Promise { await vaultsRegistry.getAddress(), await validatorsRegistry.getAddress(), await sharedMevEscrow.getAddress(), + await depositDataManager.getAddress(), EXITING_ASSETS_MIN_DELAY, ] const contract = await factory.deploy(...constructorArgs) @@ -951,6 +973,7 @@ export const ethVaultFixture = async function (): Promise { osTokenVaultController, osTokenConfig, sharedMevEscrow, + depositDataManager, poolEscrow, rewardEthToken ) diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index 404de1ae..555f5c54 100644 --- a/test/shared/rewards.ts +++ b/test/shared/rewards.ts @@ -1,7 +1,7 @@ import { ethers, network } from 'hardhat' import { Contract, Signer } from 'ethers' import { StandardMerkleTree } from '@openzeppelin/merkle-tree' -import { EthVault, IKeeperRewards, Keeper } from '../../typechain-types' +import { EthVault, IKeeperRewards, Keeper, DepositDataManager } from '../../typechain-types' import { EIP712Domain, EXITING_ASSETS_MIN_DELAY, @@ -149,7 +149,7 @@ export async function collateralizeEthV1Vault( .connect(admin) .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) const shares = await extractDepositShares(tx) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, null, admin, validatorsRegistry) // update rewards tree const vaultReward = getHarvestParams(vaultAddress, 0n, 0n) @@ -182,8 +182,9 @@ export async function collateralizeEthV1Vault( export async function collateralizeEthVault( vault: EthVaultType, keeper: Keeper, - validatorsRegistry: Contract, - admin: Signer + depositDataManager: DepositDataManager, + admin: Signer, + validatorsRegistry: Contract ) { const vaultAddress = await vault.getAddress() const balanceBefore = await ethers.provider.getBalance(vaultAddress) @@ -195,7 +196,7 @@ export async function collateralizeEthVault( .connect(admin) .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) const receivedShares = await extractDepositShares(tx) - await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) // exit validator const response = await vault.connect(admin).enterExitQueue(receivedShares, adminAddr) diff --git a/test/shared/validators.ts b/test/shared/validators.ts index 0bc9aa99..d3323d32 100644 --- a/test/shared/validators.ts +++ b/test/shared/validators.ts @@ -4,13 +4,14 @@ import { ethers, network } from 'hardhat' import { Buffer } from 'buffer' import { BytesLike, Contract, ContractTransactionResponse, Signer } from 'ethers' import bls from 'bls-eth-wasm' -import { EthVault, Keeper } from '../../typechain-types' +import { EthVault, Keeper, DepositDataManager } from '../../typechain-types' import { EIP712Domain, KeeperUpdateExitSignaturesSig, KeeperValidatorsSig, VALIDATORS_DEADLINE, VALIDATORS_MIN_ORACLES, + ZERO_BYTES32, } from './constants' import { getOraclesSignatures } from './fixtures' import { EthVaultType } from './types' @@ -284,12 +285,22 @@ export function getValidatorsMultiProof( export async function registerEthValidator( vault: EthVaultType, keeper: Keeper, - validatorsRegistry: Contract, - admin: Signer + depositDataManager: DepositDataManager, + admin: Signer, + validatorsRegistry: Contract ): Promise { const validatorsData = await createEthValidatorsData(vault) const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() - await vault.connect(admin).setValidatorsRoot(validatorsData.root) + const vaultAddress = await vault.getAddress() + if ((await vault.version()) > 1) { + if ((await depositDataManager.depositDataRoots(vaultAddress)) != ZERO_BYTES32) { + // reset validator index + await depositDataManager.connect(admin).setDepositDataRoot(vaultAddress, ZERO_BYTES32) + } + await depositDataManager.connect(admin).setDepositDataRoot(vaultAddress, validatorsData.root) + } else { + await vault.connect(admin).setValidatorsRoot(validatorsData.root) + } const validator = validatorsData.validators[0] const exitSignatureIpfsHash = exitSignatureIpfsHashes[0] const signingData = await getEthValidatorsSigningData( @@ -302,14 +313,28 @@ export async function registerEthValidator( ) const signatures = getOraclesSignatures(signingData, VALIDATORS_MIN_ORACLES) const proof = getValidatorProof(validatorsData.tree, validator, 0) - return await vault.registerValidator( - { - validatorsRegistryRoot, - validators: validator, - signatures, - exitSignaturesIpfsHash: exitSignatureIpfsHash, - deadline: VALIDATORS_DEADLINE, - }, - proof - ) + if ((await vault.version()) > 1) { + return await depositDataManager.connect(admin).registerValidator( + vaultAddress, + { + validatorsRegistryRoot, + validators: validator, + signatures, + exitSignaturesIpfsHash: exitSignatureIpfsHash, + deadline: VALIDATORS_DEADLINE, + }, + proof + ) + } else { + return await vault.registerValidator( + { + validatorsRegistryRoot, + validators: validator, + signatures, + exitSignaturesIpfsHash: exitSignatureIpfsHash, + deadline: VALIDATORS_DEADLINE, + }, + proof + ) + } } From a2e5a2057fefc7c8e13de6f443732bd90816e121 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Thu, 21 Mar 2024 20:23:19 +0200 Subject: [PATCH 17/29] Remove redundant error --- abi/Errors.json | 5 ----- contracts/libraries/Errors.sol | 1 - 2 files changed, 6 deletions(-) diff --git a/abi/Errors.json b/abi/Errors.json index f5bfbdac..668fdfe7 100644 --- a/abi/Errors.json +++ b/abi/Errors.json @@ -149,11 +149,6 @@ "name": "InvalidTokenMeta", "type": "error" }, - { - "inputs": [], - "name": "InvalidValidator", - "type": "error" - }, { "inputs": [], "name": "InvalidValidators", diff --git a/contracts/libraries/Errors.sol b/contracts/libraries/Errors.sol index 902b922b..2728932d 100644 --- a/contracts/libraries/Errors.sol +++ b/contracts/libraries/Errors.sol @@ -29,7 +29,6 @@ library Errors { error InvalidReceivedAssets(); error InvalidTokenMeta(); error UpgradeFailed(); - error InvalidValidator(); error InvalidValidators(); error DeadlineExpired(); error PermitInvalidSigner(); From 9e15aabe5be815d1229c2e0dc477d176c8c879c6 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Thu, 21 Mar 2024 20:40:02 +0200 Subject: [PATCH 18/29] Gas optimiziation --- contracts/vaults/modules/VaultEthStaking.sol | 2 +- test/__snapshots__/DepositDataManager.spec.ts.snap | 2 +- test/__snapshots__/EthGenesisVault.spec.ts.snap | 2 +- test/__snapshots__/EthVault.register.spec.ts.snap | 2 +- test/__snapshots__/KeeperValidators.spec.ts.snap | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/vaults/modules/VaultEthStaking.sol b/contracts/vaults/modules/VaultEthStaking.sol index bacee358..41968612 100644 --- a/contracts/vaults/modules/VaultEthStaking.sol +++ b/contracts/vaults/modules/VaultEthStaking.sol @@ -67,7 +67,7 @@ abstract contract VaultEthStaking is publicKey, _withdrawalCredentials(), validator[48:144], - bytes32(validator[144:validator.length]) + bytes32(validator[144:_validatorLength()]) ); emit ValidatorRegistered(publicKey); } diff --git a/test/__snapshots__/DepositDataManager.spec.ts.snap b/test/__snapshots__/DepositDataManager.spec.ts.snap index 9a5db4bd..ab367e3d 100644 --- a/test/__snapshots__/DepositDataManager.spec.ts.snap +++ b/test/__snapshots__/DepositDataManager.spec.ts.snap @@ -31,6 +31,6 @@ Object { exports[`DepositDataManager single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 331930, + "gasUsed": 331879, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index f54b1e17..9b39ee1e 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -31,7 +31,7 @@ Object { exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 310166, + "gasUsed": 310115, } `; diff --git a/test/__snapshots__/EthVault.register.spec.ts.snap b/test/__snapshots__/EthVault.register.spec.ts.snap index ca7d4fab..c44c4912 100644 --- a/test/__snapshots__/EthVault.register.spec.ts.snap +++ b/test/__snapshots__/EthVault.register.spec.ts.snap @@ -10,6 +10,6 @@ Object { exports[`EthVault - register single validator succeeds 1`] = ` Object { "calldataByteLength": 964, - "gasUsed": 298127, + "gasUsed": 298076, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index 45dd8b5d..d2d0dadd 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -17,14 +17,14 @@ Object { exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 338356, + "gasUsed": 338305, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 284631, + "gasUsed": 284580, } `; From e525a39f7a560541c553d0535bb2f7d4bf89be9e Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sat, 23 Mar 2024 00:56:18 +0200 Subject: [PATCH 19/29] Upgrade packages, fix coverage --- hardhat.config.ts | 3 +- package-lock.json | 4737 +++++++++++++++++++-------------------------- package.json | 20 +- 3 files changed, 1996 insertions(+), 2764 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 7ffbf386..a9ebdc4e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -24,7 +24,6 @@ const DEFAULT_BLOCK_GAS_LIMIT = 12450000 const MNEMONIC_PATH = "m/44'/60'/0'/0" const MNEMONIC = process.env.MNEMONIC || '' const TRACK_GAS = process.env.TRACK_GAS === 'true' -const IS_COVERAGE = process.env.COVERAGE === 'true' const BLOCK_EXPLORER_KEY = process.env.BLOCK_EXPLORER_KEY || '' const HARDHATEVM_CHAINID = 31337 @@ -58,7 +57,7 @@ const config: HardhatUserConfig = { { version: '0.8.22', settings: { - viaIR: !IS_COVERAGE, + viaIR: true, optimizer: { enabled: true, runs: 200, diff --git a/package-lock.json b/package-lock.json index 43d036d5..b3e69762 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,16 +13,16 @@ "@openzeppelin/contracts-upgradeable": "5.0.0" }, "devDependencies": { - "@chainsafe/ssz": "0.14.0", + "@chainsafe/ssz": "0.15.1", "@metamask/eth-sig-util": "7.0.1", - "@nomicfoundation/hardhat-toolbox": "4.0.0", + "@nomicfoundation/hardhat-toolbox": "5.0.0", "@openzeppelin/hardhat-upgrades": "3.0.2", - "@openzeppelin/merkle-tree": "1.0.5", - "@typescript-eslint/eslint-plugin": "6.19.1", - "@typescript-eslint/parser": "6.19.1", + "@openzeppelin/merkle-tree": "1.0.6", + "@typescript-eslint/eslint-plugin": "7.3.1", + "@typescript-eslint/parser": "7.3.1", "bls-eth-wasm": "1.1.1", - "dotenv": "16.4.1", - "eslint": "8.56.0", + "dotenv": "16.4.5", + "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-prettier": "5.1.3", "ethereumjs-wallet": "1.0.2", @@ -30,11 +30,11 @@ "hardhat-contract-sizer": "2.10.0", "hardhat-log-remover": "2.0.2", "hardhat-spdx-license-identifier": "2.2.0", - "husky": "9.0.6", + "husky": "9.0.11", "keccak256": "1.0.6", - "lint-staged": "15.2.0", + "lint-staged": "15.2.2", "mocha-chai-jest-snapshot": "1.1.4", - "prettier": "3.2.4", + "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1" } }, @@ -48,20 +48,20 @@ } }, "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==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "dev": true, "peer": true }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -90,13 +90,13 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.496.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz", - "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==", + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.535.0.tgz", + "integrity": "sha512-aY4MYfduNj+sRR37U7XxYR8wemfbKP6lx00ze2M2uubn7mZotuVrWYAafbMSXrdEMSToE5JDhr28vArSOoLcSg==", "dev": true, "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" @@ -124,43 +124,43 @@ "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", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -185,14 +185,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -259,12 +259,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -290,9 +290,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -323,9 +323,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -350,37 +350,109 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/highlight/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -537,12 +609,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -552,33 +624,33 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -596,9 +668,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -616,9 +688,9 @@ "dev": true }, "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.6.1.tgz", - "integrity": "sha512-gcENLemRR13+1MED2NeZBMA7FRS0xQPM7L2vhMqvKkjqtFT4YfjSVADq5U0iLuQLhFUJEMVuA8fbv5v+TN6O9A==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.7.1.tgz", + "integrity": "sha512-GUomb8DgkbHyKVBoLY9wMBe67oyAK9HKMjPImIocGOJuwqqxvDbVwh/ihdzyOrhEyhISqD/TxhCBDEXzLM52Vg==", "dev": true, "dependencies": { "@chainsafe/as-sha256": "^0.4.1", @@ -626,13 +698,13 @@ } }, "node_modules/@chainsafe/ssz": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.14.0.tgz", - "integrity": "sha512-KTc33pWu7ItXlzMAz5/1osOHsvhx25kpM3j7Ez+PNZLyyhIoNzAhhozvxy+ul0fCDfHbvaCRp3lJQnzsb5Iv0A==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.15.1.tgz", + "integrity": "sha512-f09UKTyYwWA1nr1BwrwsFpkXMspDDIZtwWXK1pM5mpPMnexmuPVstnN+P0M4YJ2aHcfqJXG7QOqnOwGj5Z7bUw==", "dev": true, "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/persistent-merkle-tree": "^0.6.1" + "@chainsafe/persistent-merkle-tree": "^0.7.1" } }, "node_modules/@colors/colors": { @@ -739,9 +811,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1527,9 +1599,9 @@ } }, "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==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "engines": { "node": ">=14" @@ -1615,6 +1687,15 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -1728,76 +1809,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/@jest/console/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/@jest/console/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/@jest/console/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/@jest/console/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/@jest/console/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/@jest/console/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/@jest/expect-utils": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", @@ -1863,82 +1874,12 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/@jest/transform/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/@jest/transform/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/@jest/transform/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/@jest/transform/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/@jest/transform/node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/@jest/transform/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/@jest/transform/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/@jest/types": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", @@ -1956,106 +1897,36 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/@jest/types/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/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6.0.0" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "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": ">=6.0.0" } }, - "node_modules/@jest/types/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/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/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/@jest/types/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/@jest/types/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/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" + "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -2065,9 +1936,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2105,9 +1976,9 @@ } }, "node_modules/@metamask/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-WFVcMPEkKKRCJ8DDkZUTVbLlpwgRn98F4VM/WzN89HM8PmHMnCyk/oG0AmK/seOxtik7uC7Bbi2YBC5Z5XB2zw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@metamask/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-dbIc3C7alOe0agCuBHM1h71UaEaEqOk2W8rAtEn8QGz4haH2Qq7MoK6i7v2guzvkJVVh79c+QCzIqphC3KvrJg==", "dev": true, "dependencies": { "@ethereumjs/tx": "^4.2.0", @@ -2117,7 +1988,8 @@ "debug": "^4.3.4", "pony-cause": "^2.1.10", "semver": "^7.5.4", - "superstruct": "^1.0.3" + "superstruct": "^1.0.3", + "uuid": "^9.0.1" }, "engines": { "node": ">=16.0.0" @@ -2135,7 +2007,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/hashes": { + "node_modules/@noble/curves/node_modules/@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", @@ -2147,6 +2019,18 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@noble/secp256k1": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", @@ -2194,124 +2078,228 @@ "node": ">= 8" } }, - "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/@nomicfoundation/edr": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.2.tgz", + "integrity": "sha512-HGWtjibAK1mo4I2A7nJ/fXqe/J9G54OrSPJnnkY2K8TiXotYLShGd9GvHkae3PuFjTJKm6ZgBy7tveJj5yrCfw==", "dev": true, "peer": true, - "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" + "engines": { + "node": ">= 18" }, + "optionalDependencies": { + "@nomicfoundation/edr-darwin-arm64": "0.3.2", + "@nomicfoundation/edr-darwin-x64": "0.3.2", + "@nomicfoundation/edr-linux-arm64-gnu": "0.3.2", + "@nomicfoundation/edr-linux-arm64-musl": "0.3.2", + "@nomicfoundation/edr-linux-x64-gnu": "0.3.2", + "@nomicfoundation/edr-linux-x64-musl": "0.3.2", + "@nomicfoundation/edr-win32-arm64-msvc": "0.3.2", + "@nomicfoundation/edr-win32-ia32-msvc": "0.3.2", + "@nomicfoundation/edr-win32-x64-msvc": "0.3.2" + } + }, + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.2.tgz", + "integrity": "sha512-l6wfSBUUbGJiCENT6272CDI8yoMuf0sZH56H5qz3HnAyVzenkOvmzyF6/lar54m986kdAQqWls4cLvDxiOuLxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-block/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==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.2.tgz", + "integrity": "sha512-OboExL7vEw+TRJQl3KkaEKU4K7PTdZPTInZ0fxMAtOpcWp7EKR+dQo68vc/iAOusB3xszHKxt7t+WpisItfdcg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "peer": 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" + "engines": { + "node": ">= 18" } }, - "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==", + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.2.tgz", + "integrity": "sha512-xtEK+1eg++3pHi6405NDXd80S3CGOFEGQIyVGCwjMGQFOLSzBGGCsrb/0GB4J19zd1o/8ftCd/HjZcbVAWWTLQ==", + "cpu": [ + "arm64" + ], "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" - } + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.2.tgz", + "integrity": "sha512-3cIsskJOXQ1yEVsImmCacY7O03tUTiWrmd54F05PnPFrDLkjbzodQ3b2gUWzfbzUZWl67ZTJd1CvVSzpe7XGzw==", + "cpu": [ + "arm64" ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.2.tgz", + "integrity": "sha512-ouPdphHNsyO7wqwa4hwahC5WqBglK/fIvMmhR/SXNZ9qruIpsA8ZZKIURaHMOv/2h2BbNGcyTX9uEk6+5rK/MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.2.tgz", + "integrity": "sha512-sRhwhiPbkpJMOUwXW1FZw9ks6xWyQhIhM0E8o3TXEXKSPKTE6whQLEk1R37iFITaI36vb6rSwLKTU1cb32gCoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-win32-arm64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.3.2.tgz", + "integrity": "sha512-IEwVealKfumu1HSSnama26yPuQC/uthRPK5IWtFsQUOGwOXaS1r9Bu7cGYH2jBHl3IT/JbxD4xzPq/2pM9uK0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomicfoundation/edr-win32-ia32-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.3.2.tgz", + "integrity": "sha512-jYMnf6SFgguqROswwdsjJ1wvneD/5c16pVu9OD4DxNqhKNP5bHEw6L2N4DcJ89tpXMpJ6AlOpc0QuwzddiZ3tA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.2.tgz", + "integrity": "sha512-Byn4QuWczRy/DUUQM3WjglgX/jGVUURVFaUsmIhnGg//MPlCLawubBGRqsrMuvaYedlIIJ4I2rgKvZlxdgHrqg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", + "dev": true, "peer": true, "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" + "@nomicfoundation/ethereumjs-util": "9.0.4" + } + }, + "node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", + "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "dev": true, + "peer": true, + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" } }, - "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==", + "node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", "dev": true, "peer": 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" + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/ethereum-cryptography": { + "node_modules/@nomicfoundation/ethereumjs-tx/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==", @@ -2335,36 +2323,29 @@ "setimmediate": "^1.0.5" } }, - "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, - "peer": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.2", - "crc-32": "^1.2.0" - } - }, - "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/@nomicfoundation/ethereumjs-util": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", + "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", "dev": true, "peer": true, "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", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, - "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/ethereum-cryptography": { + "node_modules/@nomicfoundation/ethereumjs-util/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==", @@ -2388,481 +2369,281 @@ "setimmediate": "^1.0.5" } }, - "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==", + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.6.tgz", + "integrity": "sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==", "dev": true, "peer": 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" + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "chai": "^4.2.0", + "ethers": "^6.1.0", + "hardhat": "^2.9.4" } }, - "node_modules/@nomicfoundation/ethereumjs-evm/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==", + "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==", "dev": true, "peer": 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/@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==", - "dev": true, - "peer": true, - "bin": { - "rlp": "bin/rlp" + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" }, - "engines": { - "node": ">=14" - } - }, - "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, - "peer": 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/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, - "peer": 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/@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" - } - ], - "peer": true, - "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" + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.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/@nomicfoundation/hardhat-ignition": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.0.tgz", + "integrity": "sha512-GbAe90O22uM67U/JnffXX+mBMn0HqCKSH+D98Tb5uWqR1N/M00cB3yY8OdqzVai7I6SuIKTc91mPdvtWt8R3MA==", "dev": true, "peer": true, "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" + "@nomicfoundation/ignition-core": "^0.15.0", + "@nomicfoundation/ignition-ui": "^0.15.0", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "prompts": "^2.4.2" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.0.1", + "hardhat": "^2.18.0" } }, - "node_modules/@nomicfoundation/ethereumjs-trie/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==", + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.0.tgz", + "integrity": "sha512-KmMNUc/jptfwdPA9ukQf+Ajon+m2vLBjDL2ze7d/vQdrS+fDxmoVwmbbEk4GOjianZcwgQOWD9dEWaj04QiowA==", "dev": true, "peer": 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" + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-ignition": "^0.15.0", + "@nomicfoundation/ignition-core": "^0.15.0", + "ethers": "^6.7.0", + "hardhat": "^2.18.0" } }, - "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/@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==", "dev": true, "peer": 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" + "ethereumjs-util": "^7.1.4" }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-tx/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, - "peer": true - }, - "node_modules/@nomicfoundation/ethereumjs-tx/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==", - "dev": true, - "peer": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" + "peerDependencies": { + "hardhat": "^2.9.5" } }, - "node_modules/@nomicfoundation/ethereumjs-tx/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/@nomicfoundation/hardhat-toolbox": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", "dev": true, - "peer": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" + "peerDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=18.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.3.0", + "typescript": ">=4.5.0" } }, - "node_modules/@nomicfoundation/ethereumjs-tx/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==", + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.5.tgz", + "integrity": "sha512-Tg4zu8RkWpyADSFIgF4FlJIUEI4VkxcvELsmbJn2OokbvH2SnUrqKmw0BBfDrtvP0hhmx8wsnrRKP5DV/oTyTA==", "dev": true, "peer": 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" + "@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" + }, + "peerDependencies": { + "hardhat": "^2.0.4" } }, - "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/@nomicfoundation/hardhat-verify/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, "peer": true, "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "ethereum-cryptography": "0.1.3" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=14" + "node": ">=4" } }, - "node_modules/@nomicfoundation/ethereumjs-util/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, - "peer": true - }, - "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/@nomicfoundation/hardhat-verify/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, "peer": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "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/@nomicfoundation/hardhat-verify/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, "peer": true, "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" + "color-name": "1.1.3" } }, - "node_modules/@nomicfoundation/ethereumjs-util/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==", + "node_modules/@nomicfoundation/hardhat-verify/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, - "peer": 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" - } + "peer": true }, - "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/@nomicfoundation/hardhat-verify/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, "peer": 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" - }, "engines": { - "node": ">=14" + "node": ">=0.8.0" } }, - "node_modules/@nomicfoundation/ethereumjs-vm/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==", + "node_modules/@nomicfoundation/hardhat-verify/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, "peer": 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" + "engines": { + "node": ">=4" } }, - "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==", + "node_modules/@nomicfoundation/hardhat-verify/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, "peer": true, - "dependencies": { - "@types/chai-as-promised": "^7.1.3", - "chai-as-promised": "^7.1.1", - "deep-eql": "^4.0.1", - "ordinal": "^1.0.3" - }, - "peerDependencies": { - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "chai": "^4.2.0", - "ethers": "^6.1.0", - "hardhat": "^2.9.4" + "bin": { + "semver": "bin/semver.js" } }, - "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/@nomicfoundation/hardhat-verify/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, "peer": true, "dependencies": { - "debug": "^4.1.1", - "lodash.isequal": "^4.5.0" + "has-flag": "^3.0.0" }, - "peerDependencies": { - "ethers": "^6.1.0", - "hardhat": "^2.0.0" + "engines": { + "node": ">=4" } - }, - "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/@nomicfoundation/ignition-core": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.0.tgz", + "integrity": "sha512-d/h8jgJHY4xIroHqdaGeTkTqjQeuzmU759AOn1Fg88cuxVhS7JM22ZI0bQWyLNSMsVstHBIo+lSMIsvm9jBF2w==", "dev": true, "peer": true, "dependencies": { - "ethereumjs-util": "^7.1.4" - }, - "peerDependencies": { - "hardhat": "^2.9.5" + "@ethersproject/address": "5.6.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.7.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" } }, - "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-4.0.0.tgz", - "integrity": "sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA==", + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", "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": "^2.0.0", - "@typechain/ethers-v6": "^0.5.0", - "@typechain/hardhat": "^9.0.0", - "@types/chai": "^4.2.0", - "@types/mocha": ">=9.1.0", - "@types/node": ">=16.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.3.0", - "typescript": ">=4.5.0" + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" } }, - "node_modules/@nomicfoundation/hardhat-verify": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.3.tgz", - "integrity": "sha512-ESbRu9by53wu6VvgwtMtm108RSmuNsVqXtzg061D+/4R7jaWh/Wl/8ve+p6SdDX7vA1Z3L02hDO1Q3BY4luLXQ==", + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dev": true, "peer": 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" + "nofilter": "^3.1.0" }, - "peerDependencies": { - "hardhat": "^2.0.4" + "engines": { + "node": ">=16" } }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.0.tgz", + "integrity": "sha512-RBvvQ0e8RcEc/LoSzNTPVKZZ5vEwlmxt7PXG278+6DqCrOqxqmh6W9PtK/4mwwvnTeBqds+8j81jDf6vJbOVBQ==", "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } + "peer": true }, "node_modules/@nomicfoundation/solidity-analyzer": { "version": "0.1.1", @@ -3144,9 +2925,9 @@ } }, "node_modules/@openzeppelin/defender-sdk-base-client": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.8.0.tgz", - "integrity": "sha512-XIJat6BW2CTM74AwG5IL0Q/aE6RXj8x7smnVKmBql4wMvmirVW+njfwzZCLhUTiBXg9AlHxIInEF14SabfIisg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.11.0.tgz", + "integrity": "sha512-HNcbRhbcMZZM5Ri5IfUwJaiJZGIrc0yboRZRlXJfG2aFS/EMfUFnQHC0tyyXtCOAoAZcn+iMlsSj5h8CoUeCfw==", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.3.6", @@ -3154,14 +2935,13 @@ } }, "node_modules/@openzeppelin/defender-sdk-deploy-client": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.8.0.tgz", - "integrity": "sha512-/tNS2EnHuA5l095wzMbIkGMDNHZLcZQ2eLUP8z+AeKaAUeR2z4qzZ1ul21kR3EJURAyoy8aULFZanLggoBWHrA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.11.0.tgz", + "integrity": "sha512-ELYVihsrTOlH7Sy5C/+Yf64hV3ICeTY2OcczOWVQ/o6rHBWKSnHSZCE/oB1cfOpyg/gCrCLXozs4NyrS5z3GUw==", "dev": true, "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@openzeppelin/defender-sdk-base-client": "^1.8.0", - "axios": "^1.4.0", + "@openzeppelin/defender-sdk-base-client": "^1.11.0", + "axios": "^1.6.7", "lodash": "^4.17.21" } }, @@ -3197,80 +2977,10 @@ } } }, - "node_modules/@openzeppelin/hardhat-upgrades/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/@openzeppelin/hardhat-upgrades/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/@openzeppelin/hardhat-upgrades/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/@openzeppelin/hardhat-upgrades/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/@openzeppelin/hardhat-upgrades/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/@openzeppelin/hardhat-upgrades/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/@openzeppelin/merkle-tree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz", - "integrity": "sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.6.tgz", + "integrity": "sha512-cGWOb2WBWbJhqvupzxjnKAwGLxxAEYPg51sk76yZ5nVe5D03mw7Vx5yo8llaIEqYhP5O39M8QlrNWclgLfKVrA==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.7.0", @@ -3335,9 +3045,9 @@ } }, "node_modules/@openzeppelin/upgrades-core": { - "version": "1.32.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.3.tgz", - "integrity": "sha512-v04RbrBOTRiIhfkTRfY4M34I2wIcuz+K1cUk/6duulsMXvRpM6/IPWeXh+1Xr1K+xedJi7gcS/pNSXfYhYNXIg==", + "version": "1.32.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.5.tgz", + "integrity": "sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==", "dev": true, "dependencies": { "cbor": "^9.0.0", @@ -3353,25 +3063,10 @@ "openzeppelin-upgrades-core": "dist/cli/cli.js" } }, - "node_modules/@openzeppelin/upgrades-core/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/@openzeppelin/upgrades-core/node_modules/cbor": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", - "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dev": true, "dependencies": { "nofilter": "^3.1.0" @@ -3380,61 +3075,6 @@ "node": ">=16" } }, - "node_modules/@openzeppelin/upgrades-core/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/@openzeppelin/upgrades-core/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/@openzeppelin/upgrades-core/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/@openzeppelin/upgrades-core/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/@openzeppelin/upgrades-core/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/@pkgr/core": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", @@ -3448,9 +3088,9 @@ } }, "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==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", "dev": true, "funding": { "url": "https://paulmillr.com/funding/" @@ -3470,6 +3110,18 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@scure/bip39": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", @@ -3483,6 +3135,18 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sentry/core": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", @@ -3599,12 +3263,12 @@ "dev": true }, "node_modules/@smithy/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz", - "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" @@ -3686,6 +3350,22 @@ "typechain": "^8.3.2" } }, + "node_modules/@typechain/hardhat/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/@types/babel__traverse": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", @@ -3705,9 +3385,9 @@ } }, "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==", + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", + "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", "dev": true, "peer": true }, @@ -3828,9 +3508,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.9.tgz", - "integrity": "sha512-CQXNuMoS/VcoAMISe5pm4JnEd1Br5jildbQEToEMQvutmv+EaQr90ry9raiudgpyDuqFiV9e4rnjSfLNq12M5w==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3849,30 +3529,12 @@ "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 - }, - "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, - "peer": 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==", - "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - } - }, - "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/qs": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", "dev": true, "peer": true }, @@ -3886,9 +3548,9 @@ } }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -3913,16 +3575,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", - "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz", + "integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/type-utils": "6.19.1", - "@typescript-eslint/utils": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/type-utils": "7.3.1", + "@typescript-eslint/utils": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3931,15 +3593,15 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -3948,26 +3610,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", - "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz", + "integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -3976,16 +3638,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz", + "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -3993,25 +3655,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", - "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz", + "integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.1", - "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/typescript-estree": "7.3.1", + "@typescript-eslint/utils": "7.3.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -4020,12 +3682,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz", + "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -4033,13 +3695,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz", + "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/visitor-keys": "7.3.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4048,7 +3710,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -4061,41 +3723,41 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz", + "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "7.3.1", + "@typescript-eslint/types": "7.3.1", + "@typescript-eslint/typescript-estree": "7.3.1", "semver": "^7.5.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz", + "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "7.3.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -4115,50 +3777,6 @@ "dev": true, "peer": true }, - "node_modules/abstract-level": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.4.tgz", - "integrity": "sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg==", - "dev": true, - "peer": true, - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-level/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" - } - ], - "peer": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -4190,16 +3808,6 @@ "node": ">=0.4.0" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", @@ -4260,9 +3868,9 @@ } }, "node_modules/amazon-cognito-identity-js": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.7.tgz", - "integrity": "sha512-tSjnM7KyAeOZ7UMah+oOZ6cW4Gf64FFcc7BE2l7MTcp7ekAPrXaCbpcW2xEpH1EiDS4cPcAouHzmCuc2tr72vQ==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz", + "integrity": "sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==", "dev": true, "dependencies": { "@aws-crypto/sha256-js": "1.2.2", @@ -4283,6 +3891,16 @@ "node": ">=0.4.2" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -4331,15 +3949,18 @@ } }, "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==", + "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": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/antlr4ts": { @@ -4386,13 +4007,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4418,16 +4042,17 @@ } }, "node_modules/array.prototype.findlast": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.3.tgz", - "integrity": "sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4437,17 +4062,18 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -4517,10 +4143,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -4529,12 +4158,12 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -4619,24 +4248,17 @@ "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, - "peer": 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==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "peer": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/blakejs": { @@ -4657,6 +4279,29 @@ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", "dev": true }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -4684,19 +4329,6 @@ "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, - "peer": 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", @@ -4719,9 +4351,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -4738,8 +4370,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -4814,14 +4446,19 @@ } }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4837,18 +4474,22 @@ } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001581", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", - "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", "dev": true, "funding": [ { @@ -4865,16 +4506,6 @@ } ] }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -4882,16 +4513,6 @@ "dev": true, "peer": 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, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", @@ -4938,17 +4559,19 @@ } }, "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==", + "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": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/charenc": { @@ -4975,16 +4598,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "peer": true, "dependencies": { "anymatch": "~3.1.2", @@ -4998,6 +4615,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -5032,32 +4652,27 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/classic-level": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.4.1.tgz", - "integrity": "sha512-qGx/KJl3bvtOHrGau2WklEZuXhS3zme+jf+fsu6Ej7W7IP/C49v7KNlWIsT1jZu0YnfzSIYDGcEWpCa1wKGWXQ==", + "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, - "hasInstallScript": true, "peer": 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": ">=6" } }, - "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==", + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, "peer": true, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-cursor": { @@ -5168,60 +4783,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/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" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cliui/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 - }, - "node_modules/cliui/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==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", @@ -5229,18 +4790,21 @@ "dev": true }, "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==", + "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.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "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==", + "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/colorette": { @@ -5310,6 +4874,19 @@ "node": ">=8.0.0" } }, + "node_modules/command-line-usage/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, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "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", @@ -5320,6 +4897,71 @@ "node": ">=8" } }, + "node_modules/command-line-usage/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, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/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, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/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, + "peer": true + }, + "node_modules/command-line-usage/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, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/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, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/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, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/command-line-usage/node_modules/typical": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", @@ -5493,6 +5135,57 @@ "node": "*" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", @@ -5560,17 +5253,20 @@ "dev": true }, "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==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -5639,21 +5335,6 @@ "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, - "peer": 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", @@ -5711,21 +5392,21 @@ } }, "node_modules/dotenv": { - "version": "16.4.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz", - "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/electron-to-chromium": { - "version": "1.4.648", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", - "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", + "version": "1.4.715", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", + "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==", "dev": true }, "node_modules/elliptic": { @@ -5780,50 +5461,57 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -5832,15 +5520,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -5873,21 +5594,24 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "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==", + "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": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escodegen": { @@ -5979,16 +5703,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -6103,21 +5827,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/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/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6128,61 +5837,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/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/eslint/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/eslint/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/eslint/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/eslint/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/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6195,18 +5849,6 @@ "node": "*" } }, - "node_modules/eslint/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/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -6506,6 +6148,18 @@ "@scure/bip39": "1.2.2" } }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethereumjs-abi": { "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", @@ -6652,10 +6306,19 @@ "setimmediate": "^1.0.5" } }, + "node_modules/ethereumjs-wallet/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==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/ethers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", - "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", + "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", "dev": true, "funding": [ { @@ -6669,7 +6332,7 @@ ], "peer": true, "dependencies": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", @@ -6879,9 +6542,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -6980,15 +6643,15 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -7036,19 +6699,18 @@ "peer": 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==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "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": ">=12" } }, "node_modules/fs-readdir-recursive": { @@ -7105,13 +6767,6 @@ "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, - "peer": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -7162,16 +6817,20 @@ } }, "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==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "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" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7208,13 +6867,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -7237,6 +6897,84 @@ "testrpc-sc": "index.js" } }, + "node_modules/ghost-testrpc/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, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/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, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/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, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ghost-testrpc/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, + "peer": true + }, + "node_modules/ghost-testrpc/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, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ghost-testrpc/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, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/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, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -7439,24 +7177,18 @@ } }, "node_modules/hardhat": { - "version": "2.19.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.19.4.tgz", - "integrity": "sha512-fTQJpqSt3Xo9Mn/WrdblNGAfcANM6XC3tAEi6YogB4s02DmTf93A8QsGb8uR0KR8TFcpcS8lgiW4ugAIYpnbrQ==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz", + "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==", "dev": true, "peer": 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/edr": "^0.3.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", @@ -7464,6 +7196,7 @@ "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", @@ -7540,80 +7273,10 @@ "hardhat": "^2.0.0" } }, - "node_modules/hardhat-contract-sizer/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/hardhat-contract-sizer/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/hardhat-contract-sizer/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/hardhat-contract-sizer/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/hardhat-contract-sizer/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/hardhat-contract-sizer/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/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==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", "dev": true, "peer": true, "dependencies": { @@ -7708,6 +7371,19 @@ "@scure/base": "~1.1.0" } }, + "node_modules/hardhat/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, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/hardhat/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", @@ -7715,6 +7391,48 @@ "dev": true, "peer": true }, + "node_modules/hardhat/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, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/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, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/hardhat/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, + "peer": true + }, + "node_modules/hardhat/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, + "peer": true, + "engines": { + "node": ">=0.8.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", @@ -7806,6 +7524,16 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/hardhat/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, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/hardhat/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -7886,6 +7614,19 @@ "semver": "bin/semver.js" } }, + "node_modules/hardhat/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, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/hardhat/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -7896,6 +7637,16 @@ "node": ">= 4.0.0" } }, + "node_modules/hardhat/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==", + "dev": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/hardhat/node_modules/ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", @@ -7928,30 +7679,30 @@ } }, "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==", + "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": ">=4" + "node": ">=8" } }, "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==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -7973,12 +7724,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -8012,9 +7763,9 @@ } }, "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==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -8125,12 +7876,12 @@ } }, "node_modules/husky": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.6.tgz", - "integrity": "sha512-EEuw/rfTiMjOfuL7pGO/i9otg1u36TXxqjIA6D9qxVjd/UXoDOsLor/BSFf5hTK50shwzCU3aVVwdXDp/lp7RA==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { - "husky": "bin.js" + "husky": "bin.mjs" }, "engines": { "node": ">=18" @@ -8173,14 +7924,25 @@ ] }, "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==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", @@ -8247,12 +8009,12 @@ "peer": true }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -8281,14 +8043,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8335,30 +8099,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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" - } - ], - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -8371,6 +8111,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -8431,9 +8186,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -8502,12 +8257,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8556,12 +8314,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -8666,76 +8424,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-diff/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/jest-diff/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/jest-diff/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/jest-diff/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/jest-diff/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/jest-diff/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/jest-get-type": { "version": "28.0.2", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", @@ -8785,76 +8473,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-matcher-utils/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/jest-message-util": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", @@ -8872,77 +8490,7 @@ "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-message-util/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/jest-message-util/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/jest-message-util/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/jest-message-util/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/jest-message-util/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/jest-message-util/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": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-regex-util": { @@ -8988,76 +8536,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-snapshot/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/jest-util": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", @@ -9075,37 +8553,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-util/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/jest-util/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/jest-util/node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -9121,45 +8568,6 @@ "node": ">=8" } }, - "node_modules/jest-util/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/jest-util/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/jest-util/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/jest-util/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/jest-worker": { "version": "28.1.3", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", @@ -9174,15 +8582,6 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, - "node_modules/jest-worker/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/jest-worker/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -9204,17 +8603,6 @@ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", "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, - "peer": 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", @@ -9269,6 +8657,13 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9383,72 +8778,14 @@ "graceful-fs": "^4.1.9" } }, - "node_modules/level": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.1.tgz", - "integrity": "sha512-oPBGkheysuw7DmzFQYyFe8NAia5jFLAgEnkgWnK3OXAuJr8qFT+xBQIwokAZPME2bhPFzS8hlYcL16m8UZrtwQ==", - "dev": true, - "peer": true, - "dependencies": { - "abstract-level": "^1.0.4", - "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, - "peer": 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==", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, "peer": true, - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder/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" - } - ], - "peer": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "node": ">=6" } }, "node_modules/levn": { @@ -9474,9 +8811,9 @@ } }, "node_modules/lint-staged": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", - "integrity": "sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==", + "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", @@ -9484,7 +8821,7 @@ "debug": "4.3.4", "execa": "8.0.1", "lilconfig": "3.0.0", - "listr2": "8.0.0", + "listr2": "8.0.1", "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", @@ -9494,39 +8831,118 @@ "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=18.12.0" + "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/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://opencollective.com/lint-staged" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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.17.0 || ^14.13 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/listr2": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.0.tgz", - "integrity": "sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==", + "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": { - "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" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/locate-path": { @@ -9601,82 +9017,6 @@ "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, - "peer": 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, - "peer": 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, - "peer": 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, - "peer": 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, - "peer": 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, - "peer": 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", @@ -9735,6 +9075,12 @@ "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", @@ -9766,6 +9112,23 @@ "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", @@ -9793,6 +9156,23 @@ "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", @@ -9842,16 +9222,6 @@ "dev": true, "peer": 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, - "peer": 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", @@ -9863,21 +9233,6 @@ "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, - "peer": 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", @@ -10015,9 +9370,9 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", + "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", "dev": true, "peer": true, "dependencies": { @@ -10028,13 +9383,12 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.0", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -10049,10 +9403,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha-chai-jest-snapshot": { @@ -10066,112 +9416,25 @@ "find-package-json": "^1.2.0", "jest-snapshot": "^28.1.1", "jest-util": "^28.1.1", - "slash": "^3.0.0", - "yargs": "^17.5.1" - }, - "peerDependencies": { - "chai": "^4.3.6" - } - }, - "node_modules/mocha-chai-jest-snapshot/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/mocha-chai-jest-snapshot/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/mocha-chai-jest-snapshot/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/mocha-chai-jest-snapshot/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/mocha-chai-jest-snapshot/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/mocha-chai-jest-snapshot/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-chai-jest-snapshot/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" + "slash": "^3.0.0", + "yargs": "^17.5.1" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "chai": "^4.3.6" } }, - "node_modules/mocha-chai-jest-snapshot/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/mocha-chai-jest-snapshot/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=12" } }, "node_modules/mocha-chai-jest-snapshot/node_modules/yargs": { @@ -10211,27 +9474,65 @@ "node": ">=6" } }, - "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==", + "node_modules/mocha/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/" + } + ], + "peer": true, + "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/mocha/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": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/mocha/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, "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, "node_modules/mocha/node_modules/minimatch": { @@ -10270,48 +9571,38 @@ "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, - "peer": 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==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", "dev": true, "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, "bin": { - "nanoid": "bin/nanoid.cjs" + "ndjson": "cli.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=10" } }, - "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, - "peer": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -10410,9 +9701,9 @@ } }, "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==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -10779,6 +10070,15 @@ "node": ">=12.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10789,9 +10089,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -10882,6 +10182,20 @@ "asap": "~2.0.6" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -10924,13 +10238,13 @@ } }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", "dev": true, "peer": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -11078,14 +10392,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -11302,45 +10617,14 @@ "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" - } - ], - "peer": true, - "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, - "peer": true - }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -11378,13 +10662,13 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", - "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, "engines": { @@ -11571,9 +10855,9 @@ } }, "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==", + "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" @@ -11614,30 +10898,32 @@ } }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11723,14 +11009,18 @@ } }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11748,6 +11038,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "peer": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -11864,9 +11161,9 @@ } }, "node_modules/solidity-ast": { - "version": "0.4.55", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.55.tgz", - "integrity": "sha512-qeEU/r/K+V5lrAw8iswf2/yfWAnSGs3WKPHI+zAFKFjX0dIBVXEU/swQ8eJQYHf6PJWUZFO2uWV4V1wEOkeQbA==", + "version": "0.4.56", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.56.tgz", + "integrity": "sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==", "dev": true, "dependencies": { "array.prototype.findlast": "^1.2.2" @@ -11879,17 +11176,16 @@ "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==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.11.tgz", + "integrity": "sha512-yy0Yk+olovBbXn0Me8BWULmmv7A69ZKkP5aTOJGOO8u61Tu2zS989erfjtFlUjDnfWtxRAVkd8BsQD704yLWHw==", "dev": true, "peer": true, "dependencies": { "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.16.0", + "@solidity-parser/parser": "^0.18.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", @@ -11897,7 +11193,7 @@ "globby": "^10.0.1", "jsonschema": "^1.2.4", "lodash": "^4.17.15", - "mocha": "10.2.0", + "mocha": "^10.2.0", "node-emoji": "^1.10.0", "pify": "^4.0.1", "recursive-readdir": "^2.2.2", @@ -11914,13 +11210,65 @@ } }, "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==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "dev": true, + "peer": true + }, + "node_modules/solidity-coverage/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, "peer": true, "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/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, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/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, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/solidity-coverage/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, + "peer": true + }, + "node_modules/solidity-coverage/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, + "peer": true, + "engines": { + "node": ">=0.8.0" } }, "node_modules/solidity-coverage/node_modules/fs-extra": { @@ -11958,6 +11306,16 @@ "node": ">=8" } }, + "node_modules/solidity-coverage/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, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/solidity-coverage/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -11968,6 +11326,19 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/solidity-coverage/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, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/solidity-coverage/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -12013,6 +11384,16 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -12122,14 +11503,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -12139,28 +11521,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12217,24 +11602,24 @@ } }, "node_modules/superstruct": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.3.tgz", - "integrity": "sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz", + "integrity": "sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==", "dev": true, "engines": { "node": ">=14.0.0" } }, "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==", + "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": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/sync-request": { @@ -12354,42 +11739,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/table/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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/table/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" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/table/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 - }, "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", @@ -12512,6 +11861,16 @@ "node": ">= 0.12" } }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12569,12 +11928,12 @@ "dev": true }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -12596,82 +11955,6 @@ "write-markdown": "dist/write-markdown.js" } }, - "node_modules/ts-command-line-args/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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-command-line-args/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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-command-line-args/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" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-command-line-args/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 - }, - "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==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.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", @@ -12930,29 +12213,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -12962,16 +12246,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -12981,14 +12266,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13002,9 +12293,9 @@ "peer": 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==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "peer": true, "bin": { @@ -13055,9 +12346,9 @@ } }, "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==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" @@ -13150,10 +12441,14 @@ "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==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -13175,9 +12470,9 @@ } }, "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==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "dev": true, "peer": true, "dependencies": { @@ -13242,16 +12537,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13260,6 +12555,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -13309,84 +12617,22 @@ "peer": true }, "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==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/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/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, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/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/wrap-ansi/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/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, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -13503,19 +12749,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 629bdf4c..c47fd739 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,16 @@ }, "homepage": "https://github.com/stakewise/v3-core#readme", "devDependencies": { - "@chainsafe/ssz": "0.14.0", + "@chainsafe/ssz": "0.15.1", "@metamask/eth-sig-util": "7.0.1", - "@nomicfoundation/hardhat-toolbox": "4.0.0", + "@nomicfoundation/hardhat-toolbox": "5.0.0", "@openzeppelin/hardhat-upgrades": "3.0.2", - "@openzeppelin/merkle-tree": "1.0.5", - "@typescript-eslint/eslint-plugin": "6.19.1", - "@typescript-eslint/parser": "6.19.1", + "@openzeppelin/merkle-tree": "1.0.6", + "@typescript-eslint/eslint-plugin": "7.3.1", + "@typescript-eslint/parser": "7.3.1", "bls-eth-wasm": "1.1.1", - "dotenv": "16.4.1", - "eslint": "8.56.0", + "dotenv": "16.4.5", + "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-prettier": "5.1.3", "ethereumjs-wallet": "1.0.2", @@ -53,11 +53,11 @@ "hardhat-contract-sizer": "2.10.0", "hardhat-log-remover": "2.0.2", "hardhat-spdx-license-identifier": "2.2.0", - "husky": "9.0.6", + "husky": "9.0.11", "keccak256": "1.0.6", - "lint-staged": "15.2.0", + "lint-staged": "15.2.2", "mocha-chai-jest-snapshot": "1.1.4", - "prettier": "3.2.4", + "prettier": "3.2.5", "prettier-plugin-solidity": "1.3.1" }, "lint-staged": { From 7d65bf58db610bbbb3992e32b2e7e2d1a7298f46 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sun, 31 Mar 2024 00:38:07 +0200 Subject: [PATCH 20/29] Move DepositDataManager from misc to validators --- contracts/{misc => validators}/DepositDataManager.sol | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contracts/{misc => validators}/DepositDataManager.sol (100%) diff --git a/contracts/misc/DepositDataManager.sol b/contracts/validators/DepositDataManager.sol similarity index 100% rename from contracts/misc/DepositDataManager.sol rename to contracts/validators/DepositDataManager.sol From d9a123550c0a97f9accceddc3a3a0c322338744e Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Sun, 31 Mar 2024 14:03:50 +0300 Subject: [PATCH 21/29] Rename keysManager to validatorsManager --- abi/IEthBlocklistErc20Vault.json | 63 ++++++++++++------- abi/IEthBlocklistVault.json | 63 ++++++++++++------- abi/IEthErc20Vault.json | 63 ++++++++++++------- abi/IEthFoxVault.json | 63 ++++++++++++------- abi/IEthGenesisVault.json | 63 ++++++++++++------- abi/IEthPrivErc20Vault.json | 63 ++++++++++++------- abi/IEthPrivVault.json | 63 ++++++++++++------- abi/IEthVault.json | 63 ++++++++++++------- abi/IVaultEthStaking.json | 63 ++++++++++++------- abi/IVaultValidators.json | 63 ++++++++++++------- contracts/interfaces/IVaultValidators.sol | 21 ++++--- contracts/vaults/modules/VaultValidators.sol | 24 +++---- test/EthVault.register.spec.ts | 30 ++++----- test/EthVault.settings.spec.ts | 20 +++--- test/EthVault.upgrade.spec.ts | 24 +++---- .../EthGenesisVault.spec.ts.snap | 2 +- .../EthVault.multicall.spec.ts.snap | 4 +- .../EthVault.settings.spec.ts.snap | 12 ++-- .../__snapshots__/RewardSplitter.spec.ts.snap | 6 +- .../SharedMevEscrow.spec.ts.snap | 2 +- 20 files changed, 488 insertions(+), 287 deletions(-) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index a20105c3..72ec9446 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -240,7 +240,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -522,6 +522,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -967,19 +986,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1283,12 +1289,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1296,12 +1302,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1528,6 +1534,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index 681538a9..897d60b3 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -215,7 +215,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -472,6 +472,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -824,19 +843,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1065,12 +1071,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1078,12 +1084,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1231,6 +1237,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index 7fe7e899..f05542a4 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -196,7 +196,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -478,6 +478,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -891,19 +910,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1194,12 +1200,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1207,12 +1213,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1421,6 +1427,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index 8dfae5e2..23d06c0f 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -252,7 +252,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -380,6 +380,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -726,19 +745,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "mevEscrow", @@ -873,12 +879,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -886,12 +892,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1039,6 +1045,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index 0e979212..443512b9 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -202,7 +202,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -484,6 +484,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -811,19 +830,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1063,12 +1069,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1076,12 +1082,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1211,6 +1217,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index d3fd4667..93b9c2f9 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -196,7 +196,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -478,6 +478,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -935,19 +954,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1238,12 +1244,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1251,12 +1257,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1496,6 +1502,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index 9c184958..fc74628c 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -428,6 +428,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -792,19 +811,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1020,12 +1026,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1033,12 +1039,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1199,6 +1205,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IEthVault.json b/abi/IEthVault.json index aac3151e..e57a00a0 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -428,6 +428,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -748,19 +767,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -976,12 +982,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -989,12 +995,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1124,6 +1130,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "vaultId", diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index bb31b994..9f991b57 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -280,6 +280,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -555,19 +574,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "mevEscrow", @@ -657,12 +663,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -670,12 +676,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -805,6 +811,19 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "withdrawableAssets", diff --git a/abi/IVaultValidators.json b/abi/IVaultValidators.json index c3d002ed..1362919d 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -72,7 +72,7 @@ "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", "name": "keysManager", "type": "address" @@ -113,6 +113,25 @@ "name": "ValidatorRegistered", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorsManager", + "type": "address" + } + ], + "name": "ValidatorsManagerUpdated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -254,19 +273,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "keysManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "queuedShares", @@ -336,12 +342,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_keysManager", - "type": "address" + "internalType": "string", + "name": "metadataIpfsHash", + "type": "string" } ], - "name": "setKeysManager", + "name": "setMetadata", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -349,12 +355,12 @@ { "inputs": [ { - "internalType": "string", - "name": "metadataIpfsHash", - "type": "string" + "internalType": "address", + "name": "_validatorsManager", + "type": "address" } ], - "name": "setMetadata", + "name": "setValidatorsManager", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -433,6 +439,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "validatorsManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "withdrawableAssets", diff --git a/contracts/interfaces/IVaultValidators.sol b/contracts/interfaces/IVaultValidators.sol index fc04b637..3526e712 100644 --- a/contracts/interfaces/IVaultValidators.sol +++ b/contracts/interfaces/IVaultValidators.sol @@ -19,11 +19,18 @@ interface IVaultValidators is IVaultAdmin, IVaultState { event ValidatorRegistered(bytes publicKey); /** - * @notice Event emitted on keys manager address update + * @notice Event emitted on keys manager address update (deprecated) * @param caller The address of the function caller * @param keysManager The address of the new keys manager */ - event KeysManagerUpdated(address indexed caller, address indexed keysManager); + event KeysManagerUpdated(address indexed caller, address keysManager); + + /** + * @notice Event emitted on validators manager address update + * @param caller The address of the function caller + * @param validatorsManager The address of the new validators manager + */ + event ValidatorsManagerUpdated(address indexed caller, address indexed validatorsManager); /** * @notice Event emitted on validators merkle tree root update (deprecated) @@ -33,10 +40,10 @@ interface IVaultValidators is IVaultAdmin, IVaultState { event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot); /** - * @notice The Vault keys manager address + * @notice The Vault validators manager address * @return The address that can register validators */ - function keysManager() external view returns (address); + function validatorsManager() external view returns (address); /** * @notice Function for registering single or multiple validators @@ -45,8 +52,8 @@ interface IVaultValidators is IVaultAdmin, IVaultState { function registerValidators(IKeeperValidators.ApprovalParams calldata keeperParams) external; /** - * @notice Function for updating the keys manager. Can only be called by the admin. Default is the deposit data manager contract. - * @param _keysManager The new keys manager address + * @notice Function for updating the validators manager. Can only be called by the admin. Default is the deposit data manager contract. + * @param _validatorsManager The new validators manager address */ - function setKeysManager(address _keysManager) external; + function setValidatorsManager(address _validatorsManager) external; } diff --git a/contracts/vaults/modules/VaultValidators.sol b/contracts/vaults/modules/VaultValidators.sol index ebf220f5..98cfe36f 100644 --- a/contracts/vaults/modules/VaultValidators.sol +++ b/contracts/vaults/modules/VaultValidators.sol @@ -33,7 +33,7 @@ abstract contract VaultValidators is /// deprecated. Deposit data management is moved to DepositDataManager contract uint256 private _validatorIndex; - address private _keysManager; + address private _validatorsManager; /** * @dev Constructor @@ -47,11 +47,11 @@ abstract contract VaultValidators is } /// @inheritdoc IVaultValidators - function keysManager() public view override returns (address) { + function validatorsManager() public view override returns (address) { // SLOAD to memory - address keysManager_ = _keysManager; - // if keysManager is not set, use deposit data manager contract address - return keysManager_ == address(0) ? _depositDataManager : keysManager_; + address validatorsManager_ = _validatorsManager; + // if validatorsManager is not set, use deposit data manager contract address + return validatorsManager_ == address(0) ? _depositDataManager : validatorsManager_; } /// @inheritdoc IVaultValidators @@ -65,7 +65,7 @@ abstract contract VaultValidators is _checkHarvested(); // check access - if (msg.sender != keysManager()) revert Errors.AccessDenied(); + if (msg.sender != validatorsManager()) revert Errors.AccessDenied(); // check validators length is valid uint256 validatorLength = _validatorLength(); @@ -93,11 +93,11 @@ abstract contract VaultValidators is } /// @inheritdoc IVaultValidators - function setKeysManager(address keysManager_) external override { + function setValidatorsManager(address validatorsManager_) external override { _checkAdmin(); - // update keysManager address - _keysManager = keysManager_; - emit KeysManagerUpdated(msg.sender, keysManager_); + // update validatorsManager address + _validatorsManager = validatorsManager_; + emit ValidatorsManagerUpdated(msg.sender, validatorsManager_); } /** @@ -138,13 +138,13 @@ abstract contract VaultValidators is IDepositDataManager(_depositDataManager).migrate( _validatorsRoot, _validatorIndex, - _keysManager + _validatorsManager ); // clean up variables delete _validatorsRoot; delete _validatorIndex; - delete _keysManager; + delete _validatorsManager; } /** diff --git a/test/EthVault.register.spec.ts b/test/EthVault.register.spec.ts index a64e6a1b..5a554124 100644 --- a/test/EthVault.register.spec.ts +++ b/test/EthVault.register.spec.ts @@ -34,7 +34,7 @@ describe('EthVault - register', () => { const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' const deadline = VALIDATORS_DEADLINE - let admin: Signer, other: Wallet, keysManager: Wallet + let admin: Signer, other: Wallet, validatorsManager: Wallet let vault: EthVault, keeper: Keeper, validatorsRegistry: Contract let validatorsData: EthValidatorsData let validatorsRegistryRoot: string @@ -42,7 +42,7 @@ describe('EthVault - register', () => { let createVault: ThenArg>['createEthVault'] before('create fixture loader', async () => { - ;[admin, other, keysManager] = (await (ethers as any).getSigners()).slice(1, 4) + ;[admin, other, validatorsManager] = (await (ethers as any).getSigners()).slice(1, 4) }) beforeEach('deploy fixture', async () => { @@ -61,7 +61,7 @@ describe('EthVault - register', () => { validatorsData = await createEthValidatorsData(vault) validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: validatorDeposit }) - await vault.connect(admin).setKeysManager(keysManager.address) + await vault.connect(admin).setValidatorsManager(validatorsManager.address) }) describe('single validator', () => { @@ -91,7 +91,7 @@ describe('EthVault - register', () => { } }) - it('fails from non-keys manager', async () => { + it('fails from non-validators manager', async () => { await expect( vault.connect(other).registerValidators(approvalParams) ).to.be.revertedWithCustomError(vault, 'AccessDenied') @@ -100,7 +100,7 @@ describe('EthVault - register', () => { it('fails with not enough withdrawable assets', async () => { await setBalance(await vault.getAddress(), ethers.parseEther('31.9')) await expect( - vault.connect(keysManager).registerValidators(approvalParams) + vault.connect(validatorsManager).registerValidators(approvalParams) ).to.be.revertedWithCustomError(vault, 'InsufficientAssets') }) @@ -124,7 +124,7 @@ describe('EthVault - register', () => { await updateRewards(keeper, [vaultReward]) await updateRewards(keeper, [vaultReward]) await expect( - vault.connect(keysManager).registerValidators(approvalParams) + vault.connect(validatorsManager).registerValidators(approvalParams) ).to.be.revertedWithCustomError(vault, 'NotHarvested') }) @@ -136,7 +136,7 @@ describe('EthVault - register', () => { ) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, validators: invalidValidator, deadline, @@ -158,7 +158,7 @@ describe('EthVault - register', () => { it('succeeds', async () => { const index = await validatorsRegistry.get_deposit_count() - const receipt = await vault.connect(keysManager).registerValidators(approvalParams) + const receipt = await vault.connect(validatorsManager).registerValidators(approvalParams) const publicKey = `0x${validator.subarray(0, 48).toString('hex')}` await expect(receipt).to.emit(vault, 'ValidatorRegistered').withArgs(publicKey) await expect(receipt) @@ -211,14 +211,14 @@ describe('EthVault - register', () => { it('fails with not enough withdrawable assets', async () => { await setBalance(await vault.getAddress(), validatorDeposit * BigInt(validators.length - 1)) await expect( - vault.connect(keysManager).registerValidators(approvalParams) + vault.connect(validatorsManager).registerValidators(approvalParams) ).to.be.revertedWithCustomError(vault, 'InsufficientAssets') }) it('fails with invalid validators count', async () => { const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, validators: Buffer.from(''), deadline, @@ -251,7 +251,7 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, deadline, validators: invalidValidatorsConcat, @@ -285,7 +285,7 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, validators: invalidValidatorsConcat, deadline, @@ -319,7 +319,7 @@ describe('EthVault - register', () => { const invalidValidatorsConcat = Buffer.concat(invalidValidators) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, validators: invalidValidatorsConcat, deadline, @@ -350,7 +350,7 @@ describe('EthVault - register', () => { for (let i = 0; i < invalidValidators.length; i++) { await expect( - vault.connect(keysManager).registerValidators({ + vault.connect(validatorsManager).registerValidators({ validatorsRegistryRoot, validators: invalidValidators[i], deadline, @@ -375,7 +375,7 @@ describe('EthVault - register', () => { const startIndex = uintSerializer.deserialize( ethers.getBytes(await validatorsRegistry.get_deposit_count()) ) - const receipt = await vault.connect(keysManager).registerValidators(approvalParams) + const receipt = await vault.connect(validatorsManager).registerValidators(approvalParams) for (let i = 0; i < validators.length; i++) { const validator = validators[i] const publicKey = toHexString(validator.subarray(0, 48)) diff --git a/test/EthVault.settings.spec.ts b/test/EthVault.settings.spec.ts index 0b99e3a1..2318ae55 100644 --- a/test/EthVault.settings.spec.ts +++ b/test/EthVault.settings.spec.ts @@ -16,11 +16,13 @@ describe('EthVault - settings', () => { const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' let createVault: ThenArg>['createEthVault'] - let admin: Wallet, keysManager: Wallet, other: Wallet, newFeeRecipient: Wallet + let admin: Wallet, validatorsManager: Wallet, other: Wallet, newFeeRecipient: Wallet let keeper: Keeper, validatorsRegistry: Contract, depositDataManager: DepositDataManager before('create fixture loader', async () => { - ;[admin, keysManager, other, newFeeRecipient] = (await (ethers as any).getSigners()).slice(1, 5) + ;[admin, validatorsManager, other, newFeeRecipient] = ( + await (ethers as any).getSigners() + ).slice(1, 5) }) beforeEach('deploy fixture', async () => { @@ -59,7 +61,7 @@ describe('EthVault - settings', () => { }) }) - describe('keys manager', () => { + describe('validators manager', () => { let vault: EthVault beforeEach('deploy vault', async () => { @@ -77,18 +79,18 @@ describe('EthVault - settings', () => { it('cannot be updated by anyone', async () => { await expect( - vault.connect(other).setKeysManager(keysManager.address) + vault.connect(other).setValidatorsManager(validatorsManager.address) ).to.be.revertedWithCustomError(vault, 'AccessDenied') }) it('can be updated by admin', async () => { // initially equals to admin - expect(await vault.keysManager()).to.be.eq(await depositDataManager.getAddress()) - const receipt = await vault.connect(admin).setKeysManager(keysManager.address) + expect(await vault.validatorsManager()).to.be.eq(await depositDataManager.getAddress()) + const receipt = await vault.connect(admin).setValidatorsManager(validatorsManager.address) await expect(receipt) - .to.emit(vault, 'KeysManagerUpdated') - .withArgs(admin.address, keysManager.address) - expect(await vault.keysManager()).to.be.eq(keysManager.address) + .to.emit(vault, 'ValidatorsManagerUpdated') + .withArgs(admin.address, validatorsManager.address) + expect(await vault.validatorsManager()).to.be.eq(validatorsManager.address) await snapshotGasCost(receipt) }) }) diff --git a/test/EthVault.upgrade.spec.ts b/test/EthVault.upgrade.spec.ts index a6092e06..360323ec 100644 --- a/test/EthVault.upgrade.spec.ts +++ b/test/EthVault.upgrade.spec.ts @@ -2,7 +2,9 @@ import { ethers } from 'hardhat' import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { + DepositDataManager, EthVault, + EthVault__factory, EthVaultFactory, EthVaultV3Mock, EthVaultV3Mock__factory, @@ -11,12 +13,11 @@ import { OsTokenVaultController, SharedMevEscrow, VaultsRegistry, - DepositDataManager, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { - deployEthVaultV1, deployEthVaultImplementation, + deployEthVaultV1, encodeEthErc20VaultInitParams, encodeEthVaultInitParams, ethVaultFixture, @@ -280,15 +281,16 @@ describe('EthVault - upgrade', () => { expect(await vault.version()).to.be.eq(1) const receipt = await vault.connect(admin).upgradeToAndCall(newImpl, '0x') - expect(await vault.version()).to.be.eq(2) - expect(await vault.implementation()).to.be.eq(newImpl) - expect(await vault.getShares(other.address)).to.be.eq(userShares) - expect(await vault.convertToAssets(userShares)).to.be.deep.eq(userAssets) - expect(await vault.osTokenPositions(other.address)).to.be.above(osTokenPosition) - expect(await vault.keysManager()).to.be.eq(await depositDataManager.getAddress()) - expect(await vault.mevEscrow()).to.be.eq(mevEscrow) - expect(await vault.totalAssets()).to.be.eq(totalAssets) - expect(await vault.totalShares()).to.be.eq(totalShares) + const vaultV2 = EthVault__factory.connect(vaultAddress, admin) + expect(await vaultV2.version()).to.be.eq(2) + expect(await vaultV2.implementation()).to.be.eq(newImpl) + expect(await vaultV2.getShares(other.address)).to.be.eq(userShares) + expect(await vaultV2.convertToAssets(userShares)).to.be.deep.eq(userAssets) + expect(await vaultV2.osTokenPositions(other.address)).to.be.above(osTokenPosition) + expect(await vaultV2.validatorsManager()).to.be.eq(await depositDataManager.getAddress()) + expect(await vaultV2.mevEscrow()).to.be.eq(mevEscrow) + expect(await vaultV2.totalAssets()).to.be.eq(totalAssets) + expect(await vaultV2.totalShares()).to.be.eq(totalShares) expect(await depositDataManager.depositDataIndexes(vaultAddress)).to.be.eq(validatorIndex) expect(await depositDataManager.depositDataRoots(vaultAddress)).to.be.eq(validatorsRoot) await snapshotGasCost(receipt) diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 9b39ee1e..4811a3b3 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,7 +10,7 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79584, + "gasUsed": 79562, } `; diff --git a/test/__snapshots__/EthVault.multicall.spec.ts.snap b/test/__snapshots__/EthVault.multicall.spec.ts.snap index 4f7d0e4e..d89f2518 100644 --- a/test/__snapshots__/EthVault.multicall.spec.ts.snap +++ b/test/__snapshots__/EthVault.multicall.spec.ts.snap @@ -3,13 +3,13 @@ exports[`EthVault - multicall can update state and queue for exit 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 168343, + "gasUsed": 168321, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 109728, + "gasUsed": 109706, } `; diff --git a/test/__snapshots__/EthVault.settings.spec.ts.snap b/test/__snapshots__/EthVault.settings.spec.ts.snap index 68ee11d3..95706cfc 100644 --- a/test/__snapshots__/EthVault.settings.spec.ts.snap +++ b/test/__snapshots__/EthVault.settings.spec.ts.snap @@ -7,16 +7,16 @@ Object { } `; -exports[`EthVault - settings keys manager can be updated by admin 1`] = ` +exports[`EthVault - settings metadata IPFS hash only admin can update 1`] = ` Object { - "calldataByteLength": 36, - "gasUsed": 52907, + "calldataByteLength": 132, + "gasUsed": 32559, } `; -exports[`EthVault - settings metadata IPFS hash only admin can update 1`] = ` +exports[`EthVault - settings validators manager can be updated by admin 1`] = ` Object { - "calldataByteLength": 132, - "gasUsed": 32559, + "calldataByteLength": 36, + "gasUsed": 52775, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index 75364a22..f8c173c8 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -3,7 +3,7 @@ exports[`RewardSplitter decrease shares owner can decrease shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 67019, + "gasUsed": 66997, } `; @@ -17,7 +17,7 @@ Object { exports[`RewardSplitter sync rewards anyone can sync rewards 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 73044, + "gasUsed": 73022, } `; @@ -31,6 +31,6 @@ Object { exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 170789, + "gasUsed": 170767, } `; diff --git a/test/__snapshots__/SharedMevEscrow.spec.ts.snap b/test/__snapshots__/SharedMevEscrow.spec.ts.snap index d26d366c..89854280 100644 --- a/test/__snapshots__/SharedMevEscrow.spec.ts.snap +++ b/test/__snapshots__/SharedMevEscrow.spec.ts.snap @@ -3,6 +3,6 @@ exports[`SharedMevEscrow vault deployment gas 1`] = ` Object { "calldataByteLength": 683, - "gasUsed": 167457, + "gasUsed": 167445, } `; From 7faacb9e04b0e29bbc3ea9c90dd54c9b03775f58 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Mon, 1 Apr 2024 20:06:46 +0300 Subject: [PATCH 22/29] Add version check to DepositDataManager --- contracts/validators/DepositDataManager.sol | 39 ++++--- test/DepositDataManager.spec.ts | 107 +++++++++++------- .../DepositDataManager.spec.ts.snap | 10 +- .../EthGenesisVault.spec.ts.snap | 4 +- .../EthVault.upgrade.spec.ts.snap | 10 +- .../KeeperValidators.spec.ts.snap | 8 +- 6 files changed, 108 insertions(+), 70 deletions(-) diff --git a/contracts/validators/DepositDataManager.sol b/contracts/validators/DepositDataManager.sol index 05daae0e..2e71a17b 100644 --- a/contracts/validators/DepositDataManager.sol +++ b/contracts/validators/DepositDataManager.sol @@ -7,6 +7,7 @@ import {IDepositDataManager} from '../interfaces/IDepositDataManager.sol'; import {IKeeperValidators} from '../interfaces/IKeeperValidators.sol'; import {IVaultAdmin} from '../interfaces/IVaultAdmin.sol'; import {IVaultValidators} from '../interfaces/IVaultValidators.sol'; +import {IVaultVersion} from '../interfaces/IVaultVersion.sol'; import {IVaultsRegistry} from '../interfaces/IVaultsRegistry.sol'; import {Errors} from '../libraries/Errors.sol'; @@ -27,6 +28,17 @@ contract DepositDataManager is IDepositDataManager { mapping(address => address) private _depositDataManagers; mapping(address => bool) private _migrated; + /** + * @dev Modifier to check if the caller is a valid vault + * @param vault The address of the vault + */ + modifier onlyValidVault(address vault) { + if (!_vaultsRegistry.vaults(vault) || IVaultVersion(vault).version() < 2) { + revert Errors.InvalidVault(); + } + _; + } + /** * @dev Constructor * @param vaultsRegistry The address of the vaults registry contract @@ -42,8 +54,10 @@ contract DepositDataManager is IDepositDataManager { } /// @inheritdoc IDepositDataManager - function setDepositDataManager(address vault, address depositDataManager) external override { - if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + function setDepositDataManager( + address vault, + address depositDataManager + ) external override onlyValidVault(vault) { // only vault admin can set deposit data manager if (msg.sender != IVaultAdmin(vault).admin()) revert Errors.AccessDenied(); @@ -53,8 +67,10 @@ contract DepositDataManager is IDepositDataManager { } /// @inheritdoc IDepositDataManager - function setDepositDataRoot(address vault, bytes32 depositDataRoot) external override { - if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); + function setDepositDataRoot( + address vault, + bytes32 depositDataRoot + ) external override onlyValidVault(vault) { if (msg.sender != getDepositDataManager(vault)) revert Errors.AccessDenied(); if (depositDataRoots[vault] == depositDataRoot) revert Errors.ValueNotChanged(); @@ -69,9 +85,7 @@ contract DepositDataManager is IDepositDataManager { address vault, IKeeperValidators.ApprovalParams calldata keeperParams, bytes32[] calldata proof - ) external override { - if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); - + ) external override onlyValidVault(vault) { // register validator IVaultValidators(vault).registerValidators(keeperParams); @@ -104,9 +118,7 @@ contract DepositDataManager is IDepositDataManager { uint256[] calldata indexes, bool[] calldata proofFlags, bytes32[] calldata proof - ) external override { - if (!_vaultsRegistry.vaults(vault)) revert Errors.InvalidVault(); - + ) external override onlyValidVault(vault) { // register validator IVaultValidators(vault).registerValidators(keeperParams); @@ -158,10 +170,9 @@ contract DepositDataManager is IDepositDataManager { bytes32 depositDataRoot, uint256 validatorIndex, address depositDataManager - ) external override { - if (!_vaultsRegistry.vaults(msg.sender) || _migrated[msg.sender]) { - revert Errors.AccessDenied(); - } + ) external override onlyValidVault(msg.sender) { + if (_migrated[msg.sender]) revert Errors.AccessDenied(); + depositDataRoots[msg.sender] = depositDataRoot; depositDataIndexes[msg.sender] = validatorIndex; _depositDataManagers[msg.sender] = depositDataManager; diff --git a/test/DepositDataManager.spec.ts b/test/DepositDataManager.spec.ts index f496bd23..5413b741 100644 --- a/test/DepositDataManager.spec.ts +++ b/test/DepositDataManager.spec.ts @@ -2,8 +2,13 @@ import { ethers } from 'hardhat' import { Contract, Signer, Wallet } from 'ethers' import { UintNumberType } from '@chainsafe/ssz' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { ThenArg } from '../helpers/types' -import { EthVault, IKeeperValidators, Keeper, DepositDataManager } from '../typechain-types' +import { + DepositDataManager, + EthVault, + IKeeperValidators, + Keeper, + VaultsRegistry, +} from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { expect } from './shared/expect' import { setBalance, toHexString } from './shared/utils' @@ -17,7 +22,12 @@ import { getWithdrawalCredentials, ValidatorsMultiProof, } from './shared/validators' -import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' +import { + deployEthVaultV1, + encodeEthVaultInitParams, + ethVaultFixture, + getOraclesSignatures, +} from './shared/fixtures' import { MAX_UINT256, PANIC_CODES, @@ -26,6 +36,7 @@ import { ZERO_ADDRESS, ZERO_BYTES32, } from './shared/constants' +import { getEthVaultV1Factory } from './shared/contracts' const gwei = 1000000000n const uintSerializer = new UintNumberType(8) @@ -41,31 +52,43 @@ describe('DepositDataManager', () => { let vault: EthVault, keeper: Keeper, validatorsRegistry: Contract, - vaultsRegistry: VaultRegistry, - depositDataManager: DepositDataManager + vaultsRegistry: VaultsRegistry, + depositDataManager: DepositDataManager, + v1Vault: Contract let validatorsData: EthValidatorsData let validatorsRegistryRoot: string - let createVault: ThenArg>['createEthVault'] - before('create fixture loader', async () => { ;[dao, admin, other, manager] = await (ethers as any).getSigners() }) beforeEach('deploy fixture', async () => { - ;({ - validatorsRegistry, - createEthVault: createVault, - keeper, - depositDataManager, - vaultsRegistry, - } = await loadFixture(ethVaultFixture)) + const fixture = await loadFixture(ethVaultFixture) + validatorsRegistry = fixture.validatorsRegistry + keeper = fixture.keeper + depositDataManager = fixture.depositDataManager + vaultsRegistry = fixture.vaultsRegistry - vault = await createVault(admin, { + vault = await fixture.createEthVault(admin, { capacity, feePercent, metadataIpfsHash, }) + v1Vault = await deployEthVaultV1( + await getEthVaultV1Factory(), + admin, + keeper, + vaultsRegistry, + validatorsRegistry, + fixture.osTokenVaultController, + fixture.osTokenConfig, + fixture.sharedMevEscrow, + encodeEthVaultInitParams({ + capacity, + feePercent, + metadataIpfsHash, + }) + ) admin = await ethers.getImpersonatedSigner(await vault.admin()) validatorsData = await createEthValidatorsData(vault) validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() @@ -79,6 +102,14 @@ describe('DepositDataManager', () => { ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') }) + it('fails for V1 vault', async () => { + await expect( + depositDataManager + .connect(admin) + .setDepositDataManager(await v1Vault.getAddress(), manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + it('fails for non-admin', async () => { await expect( depositDataManager @@ -115,6 +146,14 @@ describe('DepositDataManager', () => { ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') }) + it('fails for V1 vault', async () => { + await expect( + depositDataManager + .connect(admin) + .setDepositDataRoot(await v1Vault.getAddress(), validatorsData.root) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + }) + it('fails from non-manager', async () => { await expect( depositDataManager @@ -382,42 +421,30 @@ describe('DepositDataManager', () => { }) describe('migrate', () => { - const validatorIndex = 2 - beforeEach('set manager', async () => { await vaultsRegistry.connect(dao).addVault(other.address) }) it('fails for non-vault', async () => { await expect( - depositDataManager - .connect(admin) - .migrate(validatorsData.root, validatorIndex, manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') - }) - - it('fails for already migrated', async () => { - await depositDataManager - .connect(other) - .migrate(validatorsData.root, validatorIndex, manager.address) - - await expect( - depositDataManager - .connect(other) - .migrate(validatorsData.root, validatorIndex, manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + depositDataManager.connect(admin).migrate(validatorsData.root, 0, manager.address) + ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') }) it('succeeds', async () => { - const receipt = await depositDataManager - .connect(other) - .migrate(validatorsData.root, validatorIndex, manager.address) + const v1VaultAddress = await v1Vault.getAddress() + await vaultsRegistry.connect(dao).addVault(v1VaultAddress) + await v1Vault.connect(admin).setValidatorsRoot(validatorsData.root) + await v1Vault.connect(admin).setKeysManager(manager.address) + const receipt = await v1Vault + .connect(admin) + .upgradeToAndCall(await vault.implementation(), '0x') await expect(receipt) .to.emit(depositDataManager, 'DepositDataMigrated') - .withArgs(other.address, validatorsData.root, validatorIndex, manager.address) - expect(await depositDataManager.getDepositDataManager(other.address)).to.eq(manager.address) - expect(await depositDataManager.depositDataRoots(other.address)).to.eq(validatorsData.root) - expect(await depositDataManager.depositDataIndexes(other.address)).to.eq(validatorIndex) + .withArgs(v1VaultAddress, validatorsData.root, 0, manager.address) + expect(await depositDataManager.getDepositDataManager(v1VaultAddress)).to.eq(manager.address) + expect(await depositDataManager.depositDataRoots(v1VaultAddress)).to.eq(validatorsData.root) + expect(await depositDataManager.depositDataIndexes(v1VaultAddress)).to.eq(0) await snapshotGasCost(receipt) }) }) diff --git a/test/__snapshots__/DepositDataManager.spec.ts.snap b/test/__snapshots__/DepositDataManager.spec.ts.snap index ab367e3d..6cfa9006 100644 --- a/test/__snapshots__/DepositDataManager.spec.ts.snap +++ b/test/__snapshots__/DepositDataManager.spec.ts.snap @@ -3,34 +3,34 @@ exports[`DepositDataManager deposit data manager update succeeds 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 62126, + "gasUsed": 63461, } `; exports[`DepositDataManager deposit data root update success 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 56000, + "gasUsed": 64335, } `; exports[`DepositDataManager migrate succeeds 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 118756, + "gasUsed": 142125, } `; exports[`DepositDataManager multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3364, - "gasUsed": 684817, + "gasUsed": 686159, } `; exports[`DepositDataManager single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 331879, + "gasUsed": 333213, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 4811a3b3..d1ce30f9 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -24,14 +24,14 @@ Object { exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 649263, + "gasUsed": 650627, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 310115, + "gasUsed": 311471, } `; diff --git a/test/__snapshots__/EthVault.upgrade.spec.ts.snap b/test/__snapshots__/EthVault.upgrade.spec.ts.snap index f254c3ce..240fcff9 100644 --- a/test/__snapshots__/EthVault.upgrade.spec.ts.snap +++ b/test/__snapshots__/EthVault.upgrade.spec.ts.snap @@ -3,35 +3,35 @@ exports[`EthVault - upgrade does not modify the state variables 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 162871, + "gasUsed": 164184, } `; exports[`EthVault - upgrade does not modify the state variables 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 163547, + "gasUsed": 164992, } `; exports[`EthVault - upgrade does not modify the state variables 3`] = ` Object { "calldataByteLength": 100, - "gasUsed": 163103, + "gasUsed": 164460, } `; exports[`EthVault - upgrade does not modify the state variables 4`] = ` Object { "calldataByteLength": 100, - "gasUsed": 163767, + "gasUsed": 165256, } `; exports[`EthVault - upgrade does not modify the state variables 5`] = ` Object { "calldataByteLength": 100, - "gasUsed": 162945, + "gasUsed": 164280, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index d2d0dadd..efb04849 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -3,28 +3,28 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 691222, + "gasUsed": 692564, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 599466, + "gasUsed": 600808, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 338305, + "gasUsed": 339639, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 284580, + "gasUsed": 285914, } `; From 708645b0b4018273e06c492d60e48660e7e8c33f Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 01:10:48 +0300 Subject: [PATCH 23/29] Fix deprecated events --- abi/IEthBlocklistErc20Vault.json | 2 +- abi/IEthBlocklistVault.json | 2 +- abi/IEthErc20Vault.json | 2 +- abi/IEthFoxVault.json | 2 +- abi/IEthGenesisVault.json | 2 +- abi/IEthPrivErc20Vault.json | 2 +- abi/IEthPrivVault.json | 2 +- abi/IEthVault.json | 2 +- abi/IVaultEthStaking.json | 2 +- abi/IVaultValidators.json | 2 +- contracts/interfaces/IVaultValidators.sol | 14 +++++++------- test/__snapshots__/SharedMevEscrow.spec.ts.snap | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json index 72ec9446..4caf7d4d 100644 --- a/abi/IEthBlocklistErc20Vault.json +++ b/abi/IEthBlocklistErc20Vault.json @@ -240,7 +240,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthBlocklistVault.json b/abi/IEthBlocklistVault.json index 897d60b3..5ed5dbeb 100644 --- a/abi/IEthBlocklistVault.json +++ b/abi/IEthBlocklistVault.json @@ -215,7 +215,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthErc20Vault.json b/abi/IEthErc20Vault.json index f05542a4..b7e99ef4 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -196,7 +196,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthFoxVault.json b/abi/IEthFoxVault.json index 23d06c0f..286e2f48 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -252,7 +252,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthGenesisVault.json b/abi/IEthGenesisVault.json index 443512b9..102c2b4f 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -202,7 +202,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthPrivErc20Vault.json b/abi/IEthPrivErc20Vault.json index 93b9c2f9..245918d1 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -196,7 +196,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthPrivVault.json b/abi/IEthPrivVault.json index fc74628c..6958534d 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IEthVault.json b/abi/IEthVault.json index e57a00a0..842d67ab 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IVaultEthStaking.json b/abi/IVaultEthStaking.json index 9f991b57..bd3bcf4f 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -171,7 +171,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/abi/IVaultValidators.json b/abi/IVaultValidators.json index 1362919d..e292fe3d 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -72,7 +72,7 @@ "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", "name": "keysManager", "type": "address" diff --git a/contracts/interfaces/IVaultValidators.sol b/contracts/interfaces/IVaultValidators.sol index 3526e712..4d103682 100644 --- a/contracts/interfaces/IVaultValidators.sol +++ b/contracts/interfaces/IVaultValidators.sol @@ -23,21 +23,21 @@ interface IVaultValidators is IVaultAdmin, IVaultState { * @param caller The address of the function caller * @param keysManager The address of the new keys manager */ - event KeysManagerUpdated(address indexed caller, address keysManager); + event KeysManagerUpdated(address indexed caller, address indexed keysManager); /** - * @notice Event emitted on validators manager address update + * @notice Event emitted on validators merkle tree root update (deprecated) * @param caller The address of the function caller - * @param validatorsManager The address of the new validators manager + * @param validatorsRoot The new validators merkle tree root */ - event ValidatorsManagerUpdated(address indexed caller, address indexed validatorsManager); + event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot); /** - * @notice Event emitted on validators merkle tree root update (deprecated) + * @notice Event emitted on validators manager address update * @param caller The address of the function caller - * @param validatorsRoot The new validators merkle tree root + * @param validatorsManager The address of the new validators manager */ - event ValidatorsRootUpdated(address indexed caller, bytes32 indexed validatorsRoot); + event ValidatorsManagerUpdated(address indexed caller, address indexed validatorsManager); /** * @notice The Vault validators manager address diff --git a/test/__snapshots__/SharedMevEscrow.spec.ts.snap b/test/__snapshots__/SharedMevEscrow.spec.ts.snap index 89854280..d26d366c 100644 --- a/test/__snapshots__/SharedMevEscrow.spec.ts.snap +++ b/test/__snapshots__/SharedMevEscrow.spec.ts.snap @@ -3,6 +3,6 @@ exports[`SharedMevEscrow vault deployment gas 1`] = ` Object { "calldataByteLength": 683, - "gasUsed": 167445, + "gasUsed": 167457, } `; From 01f9b36b62f8b3c7ca3d7a1307a956c35c08be11 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 15:08:28 +0300 Subject: [PATCH 24/29] Add multicall to the DepositDataManager --- contracts/validators/DepositDataManager.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/validators/DepositDataManager.sol b/contracts/validators/DepositDataManager.sol index 2e71a17b..70b74764 100644 --- a/contracts/validators/DepositDataManager.sol +++ b/contracts/validators/DepositDataManager.sol @@ -10,13 +10,14 @@ import {IVaultValidators} from '../interfaces/IVaultValidators.sol'; import {IVaultVersion} from '../interfaces/IVaultVersion.sol'; import {IVaultsRegistry} from '../interfaces/IVaultsRegistry.sol'; import {Errors} from '../libraries/Errors.sol'; +import {Multicall} from '../base/Multicall.sol'; /** * @title DepositDataManager * @author StakeWise * @notice Defines the functionality for the Vault's deposit data management */ -contract DepositDataManager is IDepositDataManager { +contract DepositDataManager is Multicall, IDepositDataManager { IVaultsRegistry private immutable _vaultsRegistry; /// @inheritdoc IDepositDataManager From 1ba48ae22af68e08e8da220da58666d442cfbfc5 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 15:16:03 +0300 Subject: [PATCH 25/29] Update snapshots --- test/__snapshots__/DepositDataManager.spec.ts.snap | 10 +++++----- test/__snapshots__/EthGenesisVault.spec.ts.snap | 4 ++-- test/__snapshots__/EthVault.upgrade.spec.ts.snap | 10 +++++----- test/__snapshots__/KeeperValidators.spec.ts.snap | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/__snapshots__/DepositDataManager.spec.ts.snap b/test/__snapshots__/DepositDataManager.spec.ts.snap index 6cfa9006..ad84613d 100644 --- a/test/__snapshots__/DepositDataManager.spec.ts.snap +++ b/test/__snapshots__/DepositDataManager.spec.ts.snap @@ -3,34 +3,34 @@ exports[`DepositDataManager deposit data manager update succeeds 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 63461, + "gasUsed": 63707, } `; exports[`DepositDataManager deposit data root update success 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 64335, + "gasUsed": 64505, } `; exports[`DepositDataManager migrate succeeds 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 142125, + "gasUsed": 142334, } `; exports[`DepositDataManager multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3364, - "gasUsed": 686159, + "gasUsed": 687523, } `; exports[`DepositDataManager single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 333213, + "gasUsed": 333583, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index d1ce30f9..1695a7f2 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -24,14 +24,14 @@ Object { exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 650627, + "gasUsed": 651991, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 311471, + "gasUsed": 311841, } `; diff --git a/test/__snapshots__/EthVault.upgrade.spec.ts.snap b/test/__snapshots__/EthVault.upgrade.spec.ts.snap index 240fcff9..d917c4a1 100644 --- a/test/__snapshots__/EthVault.upgrade.spec.ts.snap +++ b/test/__snapshots__/EthVault.upgrade.spec.ts.snap @@ -3,35 +3,35 @@ exports[`EthVault - upgrade does not modify the state variables 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164184, + "gasUsed": 164393, } `; exports[`EthVault - upgrade does not modify the state variables 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164992, + "gasUsed": 165201, } `; exports[`EthVault - upgrade does not modify the state variables 3`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164460, + "gasUsed": 164669, } `; exports[`EthVault - upgrade does not modify the state variables 4`] = ` Object { "calldataByteLength": 100, - "gasUsed": 165256, + "gasUsed": 165465, } `; exports[`EthVault - upgrade does not modify the state variables 5`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164280, + "gasUsed": 164489, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index efb04849..c4199fc6 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -3,28 +3,28 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 692564, + "gasUsed": 693928, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 600808, + "gasUsed": 602172, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 339639, + "gasUsed": 340009, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 285914, + "gasUsed": 286284, } `; From d7b32225b1f95286ea3845b6ca05684af7c709a4 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 18:29:35 +0300 Subject: [PATCH 26/29] Update IDepositDataManager interface --- abi/IDepositDataManager.json | 19 +++++++++++++++++++ contracts/interfaces/IDepositDataManager.sol | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/abi/IDepositDataManager.json b/abi/IDepositDataManager.json index 9be53c95..acf349ad 100644 --- a/abi/IDepositDataManager.json +++ b/abi/IDepositDataManager.json @@ -148,6 +148,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/contracts/interfaces/IDepositDataManager.sol b/contracts/interfaces/IDepositDataManager.sol index 2872de4c..4b06f25d 100644 --- a/contracts/interfaces/IDepositDataManager.sol +++ b/contracts/interfaces/IDepositDataManager.sol @@ -3,13 +3,14 @@ pragma solidity =0.8.22; import {IKeeperValidators} from './IKeeperValidators.sol'; +import {IMulticall} from './IMulticall.sol'; /** * @title IDepositDataManager * @author StakeWise * @notice Defines the interface for DepositDataManager */ -interface IDepositDataManager { +interface IDepositDataManager is IMulticall { /** * @notice Event emitted on deposit data manager update * @param vault The address of the vault From e472c74abe1211e05d77847014a98ba34ffa9eaf Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 21:14:46 +0300 Subject: [PATCH 27/29] Rename DepositDataManager to DepositDataRegistry --- ...Manager.json => IDepositDataRegistry.json} | 0 ...taManager.sol => IDepositDataRegistry.sol} | 6 +- contracts/interfaces/IVaultValidators.sol | 2 +- contracts/mocks/EthPrivVaultV3Mock.sol | 4 +- contracts/mocks/EthVaultMock.sol | 4 +- contracts/mocks/EthVaultV3Mock.sol | 4 +- contracts/mocks/EthVaultV4Mock.sol | 4 +- ...ataManager.sol => DepositDataRegistry.sol} | 22 ++-- .../ethereum/EthBlocklistErc20Vault.sol | 6 +- .../vaults/ethereum/EthBlocklistVault.sol | 6 +- contracts/vaults/ethereum/EthErc20Vault.sol | 6 +- contracts/vaults/ethereum/EthGenesisVault.sol | 6 +- .../vaults/ethereum/EthPrivErc20Vault.sol | 6 +- contracts/vaults/ethereum/EthPrivVault.sol | 6 +- contracts/vaults/ethereum/EthVault.sol | 6 +- .../vaults/ethereum/custom/EthFoxVault.sol | 6 +- contracts/vaults/modules/VaultValidators.sol | 20 ++-- ...er.spec.ts => DepositDataRegistry.spec.ts} | 112 +++++++++--------- test/EthBlocklistErc20Vault.spec.ts | 10 +- test/EthBlocklistVault.spec.ts | 10 +- test/EthErc20Vault.spec.ts | 16 +-- test/EthFoxVault.spec.ts | 10 +- test/EthGenesisVault.spec.ts | 16 +-- test/EthPrivErc20Vault.spec.ts | 10 +- test/EthPrivVault.spec.ts | 8 +- test/EthVault.burn.spec.ts | 8 +- test/EthVault.deposit.spec.ts | 10 +- test/EthVault.liquidate.spec.ts | 8 +- test/EthVault.mint.spec.ts | 8 +- test/EthVault.multicall.spec.ts | 10 +- test/EthVault.redeem.spec.ts | 8 +- test/EthVault.settings.spec.ts | 10 +- test/EthVault.state.spec.ts | 8 +- test/EthVault.upgrade.spec.ts | 18 +-- test/EthVault.whitelist.spec.ts | 6 +- test/KeeperRewards.spec.ts | 8 +- test/KeeperValidators.spec.ts | 58 ++++----- test/OsToken.spec.ts | 8 +- test/PriceFeed.test.ts | 8 +- test/RewardSplitter.spec.ts | 10 +- test/VaultsRegistry.spec.ts | 2 +- ....snap => DepositDataRegistry.spec.ts.snap} | 10 +- test/shared/fixtures.ts | 34 +++--- test/shared/rewards.ts | 6 +- test/shared/validators.ts | 12 +- 45 files changed, 280 insertions(+), 276 deletions(-) rename abi/{IDepositDataManager.json => IDepositDataRegistry.json} (100%) rename contracts/interfaces/{IDepositDataManager.sol => IDepositDataRegistry.sol} (96%) rename contracts/validators/{DepositDataManager.sol => DepositDataRegistry.sol} (92%) rename test/{DepositDataManager.spec.ts => DepositDataRegistry.spec.ts} (76%) rename test/__snapshots__/{DepositDataManager.spec.ts.snap => DepositDataRegistry.spec.ts.snap} (52%) diff --git a/abi/IDepositDataManager.json b/abi/IDepositDataRegistry.json similarity index 100% rename from abi/IDepositDataManager.json rename to abi/IDepositDataRegistry.json diff --git a/contracts/interfaces/IDepositDataManager.sol b/contracts/interfaces/IDepositDataRegistry.sol similarity index 96% rename from contracts/interfaces/IDepositDataManager.sol rename to contracts/interfaces/IDepositDataRegistry.sol index 4b06f25d..f3498669 100644 --- a/contracts/interfaces/IDepositDataManager.sol +++ b/contracts/interfaces/IDepositDataRegistry.sol @@ -6,11 +6,11 @@ import {IKeeperValidators} from './IKeeperValidators.sol'; import {IMulticall} from './IMulticall.sol'; /** - * @title IDepositDataManager + * @title IDepositDataRegistry * @author StakeWise - * @notice Defines the interface for DepositDataManager + * @notice Defines the interface for DepositDataRegistry */ -interface IDepositDataManager is IMulticall { +interface IDepositDataRegistry is IMulticall { /** * @notice Event emitted on deposit data manager update * @param vault The address of the vault diff --git a/contracts/interfaces/IVaultValidators.sol b/contracts/interfaces/IVaultValidators.sol index 4d103682..b8048342 100644 --- a/contracts/interfaces/IVaultValidators.sol +++ b/contracts/interfaces/IVaultValidators.sol @@ -52,7 +52,7 @@ interface IVaultValidators is IVaultAdmin, IVaultState { function registerValidators(IKeeperValidators.ApprovalParams calldata keeperParams) external; /** - * @notice Function for updating the validators manager. Can only be called by the admin. Default is the deposit data manager contract. + * @notice Function for updating the validators manager. Can only be called by the admin. Default is the DepositDataRegistry contract. * @param _validatorsManager The new validators manager address */ function setValidatorsManager(address _validatorsManager) external; diff --git a/contracts/mocks/EthPrivVaultV3Mock.sol b/contracts/mocks/EthPrivVaultV3Mock.sol index 14f572d1..b132b726 100644 --- a/contracts/mocks/EthPrivVaultV3Mock.sol +++ b/contracts/mocks/EthPrivVaultV3Mock.sol @@ -15,7 +15,7 @@ contract EthPrivVaultV3Mock is EthPrivVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthPrivVault( @@ -25,7 +25,7 @@ contract EthPrivVaultV3Mock is EthPrivVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultMock.sol b/contracts/mocks/EthVaultMock.sol index 2ee95491..7a0bef9c 100644 --- a/contracts/mocks/EthVaultMock.sol +++ b/contracts/mocks/EthVaultMock.sol @@ -26,7 +26,7 @@ contract EthVaultMock is EthVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthVault( @@ -36,7 +36,7 @@ contract EthVaultMock is EthVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultV3Mock.sol b/contracts/mocks/EthVaultV3Mock.sol index 54650dd0..4f753dcd 100644 --- a/contracts/mocks/EthVaultV3Mock.sol +++ b/contracts/mocks/EthVaultV3Mock.sol @@ -15,7 +15,7 @@ contract EthVaultV3Mock is EthVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthVault( @@ -25,7 +25,7 @@ contract EthVaultV3Mock is EthVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/mocks/EthVaultV4Mock.sol b/contracts/mocks/EthVaultV4Mock.sol index d73e8211..47b915d1 100644 --- a/contracts/mocks/EthVaultV4Mock.sol +++ b/contracts/mocks/EthVaultV4Mock.sol @@ -13,7 +13,7 @@ contract EthVaultV4Mock is EthVaultV3Mock { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthVaultV3Mock( @@ -23,7 +23,7 @@ contract EthVaultV4Mock is EthVaultV3Mock { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/validators/DepositDataManager.sol b/contracts/validators/DepositDataRegistry.sol similarity index 92% rename from contracts/validators/DepositDataManager.sol rename to contracts/validators/DepositDataRegistry.sol index 70b74764..986470fa 100644 --- a/contracts/validators/DepositDataManager.sol +++ b/contracts/validators/DepositDataRegistry.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.22; import {MerkleProof} from '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol'; -import {IDepositDataManager} from '../interfaces/IDepositDataManager.sol'; +import {IDepositDataRegistry} from '../interfaces/IDepositDataRegistry.sol'; import {IKeeperValidators} from '../interfaces/IKeeperValidators.sol'; import {IVaultAdmin} from '../interfaces/IVaultAdmin.sol'; import {IVaultValidators} from '../interfaces/IVaultValidators.sol'; @@ -13,17 +13,17 @@ import {Errors} from '../libraries/Errors.sol'; import {Multicall} from '../base/Multicall.sol'; /** - * @title DepositDataManager + * @title DepositDataRegistry * @author StakeWise * @notice Defines the functionality for the Vault's deposit data management */ -contract DepositDataManager is Multicall, IDepositDataManager { +contract DepositDataRegistry is Multicall, IDepositDataRegistry { IVaultsRegistry private immutable _vaultsRegistry; - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry mapping(address => uint256) public override depositDataIndexes; - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry mapping(address => bytes32) public override depositDataRoots; mapping(address => address) private _depositDataManagers; @@ -48,13 +48,13 @@ contract DepositDataManager is Multicall, IDepositDataManager { _vaultsRegistry = IVaultsRegistry(vaultsRegistry); } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function getDepositDataManager(address vault) public view override returns (address) { address depositDataManager = _depositDataManagers[vault]; return depositDataManager == address(0) ? IVaultAdmin(vault).admin() : depositDataManager; } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function setDepositDataManager( address vault, address depositDataManager @@ -67,7 +67,7 @@ contract DepositDataManager is Multicall, IDepositDataManager { emit DepositDataManagerUpdated(vault, depositDataManager); } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function setDepositDataRoot( address vault, bytes32 depositDataRoot @@ -81,7 +81,7 @@ contract DepositDataManager is Multicall, IDepositDataManager { emit DepositDataRootUpdated(vault, depositDataRoot); } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function registerValidator( address vault, IKeeperValidators.ApprovalParams calldata keeperParams, @@ -112,7 +112,7 @@ contract DepositDataManager is Multicall, IDepositDataManager { } } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function registerValidators( address vault, IKeeperValidators.ApprovalParams calldata keeperParams, @@ -166,7 +166,7 @@ contract DepositDataManager is Multicall, IDepositDataManager { depositDataIndexes[vault] = currentIndex; } - /// @inheritdoc IDepositDataManager + /// @inheritdoc IDepositDataRegistry function migrate( bytes32 depositDataRoot, uint256 validatorIndex, diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol index 9ae63750..d09b7dcc 100644 --- a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -36,7 +36,7 @@ contract EthBlocklistErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -47,7 +47,7 @@ contract EthBlocklistErc20Vault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthErc20Vault( @@ -57,7 +57,7 @@ contract EthBlocklistErc20Vault is osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthBlocklistVault.sol b/contracts/vaults/ethereum/EthBlocklistVault.sol index b25c0ee3..6ae504d4 100644 --- a/contracts/vaults/ethereum/EthBlocklistVault.sol +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -30,7 +30,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -41,7 +41,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthVault( @@ -51,7 +51,7 @@ contract EthBlocklistVault is Initializable, EthVault, VaultBlocklist, IEthBlock osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthErc20Vault.sol b/contracts/vaults/ethereum/EthErc20Vault.sol index b7058dee..f7733990 100644 --- a/contracts/vaults/ethereum/EthErc20Vault.sol +++ b/contracts/vaults/ethereum/EthErc20Vault.sol @@ -53,7 +53,7 @@ contract EthErc20Vault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -64,11 +64,11 @@ contract EthErc20Vault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultValidators(depositDataManager) + VaultValidators(depositDataRegistry) VaultEnterExit(exitingAssetsClaimDelay) VaultOsToken(osTokenVaultController, osTokenConfig) VaultMev(sharedMevEscrow) diff --git a/contracts/vaults/ethereum/EthGenesisVault.sol b/contracts/vaults/ethereum/EthGenesisVault.sol index 52746796..355d60bb 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -44,7 +44,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param poolEscrow The address of the pool escrow from StakeWise v2 * @param rewardEthToken The address of the rETH2 token from StakeWise v2 * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking @@ -57,7 +57,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, address poolEscrow, address rewardEthToken, uint256 exitingAssetsClaimDelay @@ -69,7 +69,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) { diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index 6f467dea..8936c87b 100644 --- a/contracts/vaults/ethereum/EthPrivErc20Vault.sol +++ b/contracts/vaults/ethereum/EthPrivErc20Vault.sol @@ -31,7 +31,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -42,7 +42,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthErc20Vault( @@ -52,7 +52,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthPrivVault.sol b/contracts/vaults/ethereum/EthPrivVault.sol index ec05b2f9..9a0e84b0 100644 --- a/contracts/vaults/ethereum/EthPrivVault.sol +++ b/contracts/vaults/ethereum/EthPrivVault.sol @@ -30,7 +30,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -41,7 +41,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) EthVault( @@ -51,7 +51,7 @@ contract EthPrivVault is Initializable, EthVault, VaultWhitelist, IEthPrivVault osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, exitingAssetsClaimDelay ) {} diff --git a/contracts/vaults/ethereum/EthVault.sol b/contracts/vaults/ethereum/EthVault.sol index da041dc4..5d22410d 100644 --- a/contracts/vaults/ethereum/EthVault.sol +++ b/contracts/vaults/ethereum/EthVault.sol @@ -49,7 +49,7 @@ contract EthVault is * @param osTokenVaultController The address of the OsTokenVaultController contract * @param osTokenConfig The address of the OsTokenConfig contract * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -60,11 +60,11 @@ contract EthVault is address osTokenVaultController, address osTokenConfig, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultValidators(depositDataManager) + VaultValidators(depositDataRegistry) VaultEnterExit(exitingAssetsClaimDelay) VaultOsToken(osTokenVaultController, osTokenConfig) VaultMev(sharedMevEscrow) diff --git a/contracts/vaults/ethereum/custom/EthFoxVault.sol b/contracts/vaults/ethereum/custom/EthFoxVault.sol index 296a311f..2efbd617 100644 --- a/contracts/vaults/ethereum/custom/EthFoxVault.sol +++ b/contracts/vaults/ethereum/custom/EthFoxVault.sol @@ -46,7 +46,7 @@ contract EthFoxVault is * @param _vaultsRegistry The address of the VaultsRegistry contract * @param _validatorsRegistry The contract address used for registering validators in beacon chain * @param sharedMevEscrow The address of the shared MEV escrow - * @param depositDataManager The address of the DepositDataManager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking */ /// @custom:oz-upgrades-unsafe-allow constructor @@ -55,11 +55,11 @@ contract EthFoxVault is address _vaultsRegistry, address _validatorsRegistry, address sharedMevEscrow, - address depositDataManager, + address depositDataRegistry, uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultValidators(depositDataManager) + VaultValidators(depositDataRegistry) VaultEnterExit(exitingAssetsClaimDelay) VaultMev(sharedMevEscrow) { diff --git a/contracts/vaults/modules/VaultValidators.sol b/contracts/vaults/modules/VaultValidators.sol index 98cfe36f..20ad3aa4 100644 --- a/contracts/vaults/modules/VaultValidators.sol +++ b/contracts/vaults/modules/VaultValidators.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.22; import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; import {MerkleProof} from '@openzeppelin/contracts/utils/cryptography/MerkleProof.sol'; import {IKeeperValidators} from '../../interfaces/IKeeperValidators.sol'; -import {IDepositDataManager} from '../../interfaces/IDepositDataManager.sol'; +import {IDepositDataRegistry} from '../../interfaces/IDepositDataRegistry.sol'; import {IVaultValidators} from '../../interfaces/IVaultValidators.sol'; import {Errors} from '../../libraries/Errors.sol'; import {VaultImmutables} from './VaultImmutables.sol'; @@ -25,12 +25,12 @@ abstract contract VaultValidators is IVaultValidators { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - address private immutable _depositDataManager; + address private immutable _depositDataRegistry; - /// deprecated. Deposit data management is moved to DepositDataManager contract + /// deprecated. Deposit data management is moved to DepositDataRegistry contract bytes32 private _validatorsRoot; - /// deprecated. Deposit data management is moved to DepositDataManager contract + /// deprecated. Deposit data management is moved to DepositDataRegistry contract uint256 private _validatorIndex; address private _validatorsManager; @@ -39,19 +39,19 @@ abstract contract VaultValidators is * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, * its value would be shared among all proxies pointing to a given contract instead of each proxy’s storage. - * @param depositDataManager The address of the deposit data manager contract + * @param depositDataRegistry The address of the DepositDataRegistry contract */ /// @custom:oz-upgrades-unsafe-allow constructor - constructor(address depositDataManager) { - _depositDataManager = depositDataManager; + constructor(address depositDataRegistry) { + _depositDataRegistry = depositDataRegistry; } /// @inheritdoc IVaultValidators function validatorsManager() public view override returns (address) { // SLOAD to memory address validatorsManager_ = _validatorsManager; - // if validatorsManager is not set, use deposit data manager contract address - return validatorsManager_ == address(0) ? _depositDataManager : validatorsManager_; + // if validatorsManager is not set, use DepositDataRegistry contract address + return validatorsManager_ == address(0) ? _depositDataRegistry : validatorsManager_; } /// @inheritdoc IVaultValidators @@ -135,7 +135,7 @@ abstract contract VaultValidators is * @dev Initializes the V2 of the VaultValidators contract */ function __VaultValidators_initV2() internal onlyInitializing { - IDepositDataManager(_depositDataManager).migrate( + IDepositDataRegistry(_depositDataRegistry).migrate( _validatorsRoot, _validatorIndex, _validatorsManager diff --git a/test/DepositDataManager.spec.ts b/test/DepositDataRegistry.spec.ts similarity index 76% rename from test/DepositDataManager.spec.ts rename to test/DepositDataRegistry.spec.ts index 5413b741..acba758b 100644 --- a/test/DepositDataManager.spec.ts +++ b/test/DepositDataRegistry.spec.ts @@ -3,7 +3,7 @@ import { Contract, Signer, Wallet } from 'ethers' import { UintNumberType } from '@chainsafe/ssz' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { - DepositDataManager, + DepositDataRegistry, EthVault, IKeeperValidators, Keeper, @@ -41,7 +41,7 @@ import { getEthVaultV1Factory } from './shared/contracts' const gwei = 1000000000n const uintSerializer = new UintNumberType(8) -describe('DepositDataManager', () => { +describe('DepositDataRegistry', () => { const validatorDeposit = ethers.parseEther('32') const capacity = MAX_UINT256 const feePercent = 1000 @@ -53,7 +53,7 @@ describe('DepositDataManager', () => { keeper: Keeper, validatorsRegistry: Contract, vaultsRegistry: VaultsRegistry, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, v1Vault: Contract let validatorsData: EthValidatorsData let validatorsRegistryRoot: string @@ -66,7 +66,7 @@ describe('DepositDataManager', () => { const fixture = await loadFixture(ethVaultFixture) validatorsRegistry = fixture.validatorsRegistry keeper = fixture.keeper - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry vaultsRegistry = fixture.vaultsRegistry vault = await fixture.createEthVault(admin, { @@ -98,85 +98,85 @@ describe('DepositDataManager', () => { describe('deposit data manager update', () => { it('fails for non-vault', async () => { await expect( - depositDataManager.connect(admin).setDepositDataManager(other.address, manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + depositDataRegistry.connect(admin).setDepositDataManager(other.address, manager.address) + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails for V1 vault', async () => { await expect( - depositDataManager + depositDataRegistry .connect(admin) .setDepositDataManager(await v1Vault.getAddress(), manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails for non-admin', async () => { await expect( - depositDataManager + depositDataRegistry .connect(other) .setDepositDataManager(await vault.getAddress(), manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + ).to.be.revertedWithCustomError(depositDataRegistry, 'AccessDenied') }) it('succeeds', async () => { const vaultAddr = await vault.getAddress() const adminAddr = await admin.getAddress() - expect(await depositDataManager.getDepositDataManager(vaultAddr)).to.eq(adminAddr) - const receipt = await depositDataManager + expect(await depositDataRegistry.getDepositDataManager(vaultAddr)).to.eq(adminAddr) + const receipt = await depositDataRegistry .connect(admin) .setDepositDataManager(vaultAddr, manager.address) await expect(receipt) - .to.emit(depositDataManager, 'DepositDataManagerUpdated') + .to.emit(depositDataRegistry, 'DepositDataManagerUpdated') .withArgs(vaultAddr, manager.address) - expect(await depositDataManager.getDepositDataManager(vaultAddr)).to.eq(manager.address) + expect(await depositDataRegistry.getDepositDataManager(vaultAddr)).to.eq(manager.address) await snapshotGasCost(receipt) }) }) describe('deposit data root update', () => { beforeEach('set manager', async () => { - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataManager(await vault.getAddress(), manager.address) }) it('fails for invalid vault', async () => { await expect( - depositDataManager.connect(manager).setDepositDataRoot(other.address, validatorsData.root) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + depositDataRegistry.connect(manager).setDepositDataRoot(other.address, validatorsData.root) + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails for V1 vault', async () => { await expect( - depositDataManager + depositDataRegistry .connect(admin) .setDepositDataRoot(await v1Vault.getAddress(), validatorsData.root) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails from non-manager', async () => { await expect( - depositDataManager + depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), validatorsData.root) - ).to.be.revertedWithCustomError(depositDataManager, 'AccessDenied') + ).to.be.revertedWithCustomError(depositDataRegistry, 'AccessDenied') }) it('fails for same root', async () => { const vaultAddr = await vault.getAddress() - await depositDataManager.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) + await depositDataRegistry.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) await expect( - depositDataManager.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) - ).to.be.revertedWithCustomError(depositDataManager, 'ValueNotChanged') + depositDataRegistry.connect(manager).setDepositDataRoot(vaultAddr, validatorsData.root) + ).to.be.revertedWithCustomError(depositDataRegistry, 'ValueNotChanged') }) it('success', async () => { const vaultAddr = await vault.getAddress() - const receipt = await depositDataManager + const receipt = await depositDataRegistry .connect(manager) .setDepositDataRoot(vaultAddr, validatorsData.root) await expect(receipt) - .to.emit(depositDataManager, 'DepositDataRootUpdated') + .to.emit(depositDataRegistry, 'DepositDataRootUpdated') .withArgs(vaultAddr, validatorsData.root) await snapshotGasCost(receipt) }) @@ -190,7 +190,7 @@ describe('DepositDataManager', () => { beforeEach(async () => { validator = validatorsData.validators[0] proof = getValidatorProof(validatorsData.tree, validator, 0) - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), validatorsData.root) const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] @@ -216,20 +216,24 @@ describe('DepositDataManager', () => { it('fails for invalid vault', async () => { await expect( - depositDataManager.registerValidator(other.address, approvalParams, proof) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + depositDataRegistry.registerValidator(other.address, approvalParams, proof) + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails with invalid proof', async () => { const invalidProof = getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) await expect( - depositDataManager.registerValidator(await vault.getAddress(), approvalParams, invalidProof) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidProof') + depositDataRegistry.registerValidator( + await vault.getAddress(), + approvalParams, + invalidProof + ) + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidProof') }) it('succeeds', async () => { const index = await validatorsRegistry.get_deposit_count() - const receipt = await depositDataManager.registerValidator( + const receipt = await depositDataRegistry.registerValidator( await vault.getAddress(), approvalParams, proof @@ -245,12 +249,12 @@ describe('DepositDataManager', () => { toHexString(validator.subarray(48, 144)), index ) - expect(await depositDataManager.depositDataIndexes(await vault.getAddress())).to.eq(1) + expect(await depositDataRegistry.depositDataIndexes(await vault.getAddress())).to.eq(1) - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), ZERO_BYTES32) - expect(await depositDataManager.depositDataIndexes(await vault.getAddress())).to.eq(0) + expect(await depositDataRegistry.depositDataIndexes(await vault.getAddress())).to.eq(0) await snapshotGasCost(receipt) }) }) @@ -270,7 +274,7 @@ describe('DepositDataManager', () => { const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] const sortedVals = multiProof.leaves.map((v) => v[0]) const vaultAddr = await vault.getAddress() - await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) + await depositDataRegistry.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) indexes = validators.map((v) => sortedVals.indexOf(v)) const balance = validatorDeposit * BigInt(validators.length) + @@ -299,20 +303,20 @@ describe('DepositDataManager', () => { it('fails for invalid vault', async () => { await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( other.address, approvalParams, indexes, multiProof.proofFlags, multiProof.proof ) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('fails with invalid validators count', async () => { const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { validatorsRegistryRoot, @@ -346,30 +350,30 @@ describe('DepositDataManager', () => { ) await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), approvalParams, indexes, invalidMultiProof.proofFlags, invalidMultiProof.proof ) - ).to.be.revertedWithCustomError(depositDataManager, 'MerkleProofInvalidMultiproof') + ).to.be.revertedWithCustomError(depositDataRegistry, 'MerkleProofInvalidMultiproof') }) it('fails with invalid indexes', async () => { const vaultAddr = await vault.getAddress() await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( vaultAddr, approvalParams, [], multiProof.proofFlags, multiProof.proof ) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidValidators') + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidValidators') await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( vaultAddr, approvalParams, indexes.map((i) => i + 1), @@ -379,14 +383,14 @@ describe('DepositDataManager', () => { ).to.be.revertedWithPanic(PANIC_CODES.OUT_OF_BOUND_INDEX) await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( vaultAddr, approvalParams, indexes.sort(() => 0.5 - Math.random()), multiProof.proofFlags, multiProof.proof ) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidProof') + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidProof') }) it('succeeds', async () => { @@ -394,7 +398,7 @@ describe('DepositDataManager', () => { ethers.getBytes(await validatorsRegistry.get_deposit_count()) ) const vaultAddress = await vault.getAddress() - const receipt = await depositDataManager.registerValidators( + const receipt = await depositDataRegistry.registerValidators( vaultAddress, approvalParams, indexes, @@ -415,7 +419,7 @@ describe('DepositDataManager', () => { toHexString(Buffer.from(uintSerializer.serialize(startIndex + i))) ) } - expect(await depositDataManager.depositDataIndexes(vaultAddress)).to.eq(validators.length) + expect(await depositDataRegistry.depositDataIndexes(vaultAddress)).to.eq(validators.length) await snapshotGasCost(receipt) }) }) @@ -427,8 +431,8 @@ describe('DepositDataManager', () => { it('fails for non-vault', async () => { await expect( - depositDataManager.connect(admin).migrate(validatorsData.root, 0, manager.address) - ).to.be.revertedWithCustomError(depositDataManager, 'InvalidVault') + depositDataRegistry.connect(admin).migrate(validatorsData.root, 0, manager.address) + ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidVault') }) it('succeeds', async () => { @@ -440,11 +444,11 @@ describe('DepositDataManager', () => { .connect(admin) .upgradeToAndCall(await vault.implementation(), '0x') await expect(receipt) - .to.emit(depositDataManager, 'DepositDataMigrated') + .to.emit(depositDataRegistry, 'DepositDataMigrated') .withArgs(v1VaultAddress, validatorsData.root, 0, manager.address) - expect(await depositDataManager.getDepositDataManager(v1VaultAddress)).to.eq(manager.address) - expect(await depositDataManager.depositDataRoots(v1VaultAddress)).to.eq(validatorsData.root) - expect(await depositDataManager.depositDataIndexes(v1VaultAddress)).to.eq(0) + expect(await depositDataRegistry.getDepositDataManager(v1VaultAddress)).to.eq(manager.address) + expect(await depositDataRegistry.depositDataRoots(v1VaultAddress)).to.eq(validatorsData.root) + expect(await depositDataRegistry.depositDataIndexes(v1VaultAddress)).to.eq(0) await snapshotGasCost(receipt) }) }) diff --git a/test/EthBlocklistErc20Vault.spec.ts b/test/EthBlocklistErc20Vault.spec.ts index 9945a8b4..6fe068b1 100644 --- a/test/EthBlocklistErc20Vault.spec.ts +++ b/test/EthBlocklistErc20Vault.spec.ts @@ -5,7 +5,7 @@ import { EthBlocklistErc20Vault, IKeeperRewards, Keeper, - DepositDataManager, + DepositDataRegistry, OsTokenVaultController, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' @@ -33,7 +33,7 @@ describe('EthBlocklistErc20Vault', () => { keeper: Keeper, validatorsRegistry: Contract, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry beforeEach('deploy fixtures', async () => { ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() @@ -49,7 +49,7 @@ describe('EthBlocklistErc20Vault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry }) it('has id', async () => { @@ -117,7 +117,7 @@ describe('EthBlocklistErc20Vault', () => { }) it('cannot update state and call by blocked sender', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -187,7 +187,7 @@ describe('EthBlocklistErc20Vault', () => { let osTokenShares: bigint beforeEach(async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthBlocklistVault.spec.ts b/test/EthBlocklistVault.spec.ts index ec6f543a..8d7d4008 100644 --- a/test/EthBlocklistVault.spec.ts +++ b/test/EthBlocklistVault.spec.ts @@ -6,7 +6,7 @@ import { IKeeperRewards, Keeper, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -31,7 +31,7 @@ describe('EthBlocklistVault', () => { keeper: Keeper, validatorsRegistry: Contract, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry beforeEach('deploy fixtures', async () => { ;[sender, admin, other, blocklistManager] = await (ethers as any).getSigners() @@ -45,7 +45,7 @@ describe('EthBlocklistVault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry }) it('has id', async () => { @@ -78,7 +78,7 @@ describe('EthBlocklistVault', () => { }) it('cannot update state and call by blocked sender', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -148,7 +148,7 @@ describe('EthBlocklistVault', () => { let osTokenShares: bigint beforeEach(async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthErc20Vault.spec.ts b/test/EthErc20Vault.spec.ts index 9f22b633..6c4beedf 100644 --- a/test/EthErc20Vault.spec.ts +++ b/test/EthErc20Vault.spec.ts @@ -8,7 +8,7 @@ import { VaultsRegistry, OsTokenConfig, SharedMevEscrow, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { @@ -46,7 +46,7 @@ describe('EthErc20Vault', () => { vaultsRegistry: VaultsRegistry, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry beforeEach('deploy fixtures', async () => { ;[sender, receiver, admin] = (await (ethers as any).getSigners()).slice(1, 4) @@ -65,7 +65,7 @@ describe('EthErc20Vault', () => { osTokenConfig = fixture.osTokenConfig vaultsRegistry = fixture.vaultsRegistry sharedMevEscrow = fixture.sharedMevEscrow - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry }) it('has id', async () => { @@ -121,7 +121,7 @@ describe('EthErc20Vault', () => { }) it('enter exit queue emits transfer event', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) expect(await vault.totalExitingAssets()).to.be.eq(0) const totalExitingBefore = await vault.totalExitingAssets() const totalAssetsBefore = await vault.totalAssets() @@ -171,7 +171,7 @@ describe('EthErc20Vault', () => { await vault .connect(admin) .deposit(await admin.getAddress(), ZERO_ADDRESS, { value: validatorDeposit }) - await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) + await registerEthValidator(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const rewardsTree = await updateRewards(keeper, [ { vault: await vault.getAddress(), reward: 0n, unlockedMevReward: 0n }, @@ -200,7 +200,7 @@ describe('EthErc20Vault', () => { }) it('cannot transfer vault shares when unharvested and osToken minted', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const assets = ethers.parseEther('1') const shares = await vault.convertToShares(assets) const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) @@ -220,7 +220,7 @@ describe('EthErc20Vault', () => { }) it('cannot transfer vault shares when LTV is violated', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const assets = ethers.parseEther('2') const shares = await vault.convertToShares(assets) const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) @@ -237,7 +237,7 @@ describe('EthErc20Vault', () => { }) it('can transfer vault shares when LTV is not violated', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const assets = ethers.parseEther('2') const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) const transferShares = await vault.convertToShares(ethers.parseEther('0.1')) diff --git a/test/EthFoxVault.spec.ts b/test/EthFoxVault.spec.ts index 39d61760..0599d8df 100644 --- a/test/EthFoxVault.spec.ts +++ b/test/EthFoxVault.spec.ts @@ -2,7 +2,7 @@ import { ethers } from 'hardhat' import keccak256 from 'keccak256' import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { Keeper, IKeeperRewards, EthFoxVault, DepositDataManager } from '../typechain-types' +import { Keeper, IKeeperRewards, EthFoxVault, DepositDataRegistry } from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -25,7 +25,7 @@ describe('EthFoxVault', () => { let vault: EthFoxVault, keeper: Keeper, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createFoxVault: ThenArg>['createEthFoxVault'] @@ -38,7 +38,7 @@ describe('EthFoxVault', () => { createEthFoxVault: createFoxVault, keeper, validatorsRegistry, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createFoxVault(admin, { capacity, @@ -131,7 +131,7 @@ describe('EthFoxVault', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) @@ -224,7 +224,7 @@ describe('EthFoxVault', () => { }) it('blocklist manager can eject all of the user assets for collateralized vault', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const tx = await vault.connect(blocklistManager).ejectUser(sender.address) const positionTicket = await extractExitPositionTicket(tx) diff --git a/test/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 83a72967..2e0915d4 100644 --- a/test/EthGenesisVault.spec.ts +++ b/test/EthGenesisVault.spec.ts @@ -5,7 +5,7 @@ import { Keeper, PoolEscrowMock, LegacyRewardTokenMock, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { createDepositorMock, ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { expect } from './shared/expect' @@ -52,7 +52,7 @@ describe('EthGenesisVault', () => { let vault: EthGenesisVault, keeper: Keeper, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let poolEscrow: PoolEscrowMock let rewardEthToken: LegacyRewardTokenMock @@ -65,7 +65,7 @@ describe('EthGenesisVault', () => { async function collatEthVault() { if (MAINNET_FORK.enabled) return - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) } beforeEach('deploy fixtures', async () => { @@ -73,7 +73,7 @@ describe('EthGenesisVault', () => { const fixture = await loadFixture(ethVaultFixture) keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry ;[vault, rewardEthToken, poolEscrow] = await fixture.createEthGenesisVault(admin, { capacity, feePercent, @@ -285,7 +285,7 @@ describe('EthGenesisVault', () => { const tx = await registerEthValidator( vault, keeper, - depositDataManager, + depositDataRegistry, admin, validatorsRegistry ) @@ -302,8 +302,8 @@ describe('EthGenesisVault', () => { const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() const vaultAddr = await vault.getAddress() // reset validator index - await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, ZERO_BYTES32) - await depositDataManager.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) + await depositDataRegistry.connect(admin).setDepositDataRoot(vaultAddr, ZERO_BYTES32) + await depositDataRegistry.connect(admin).setDepositDataRoot(vaultAddr, validatorsData.root) const proof = getValidatorsMultiProof(validatorsData.tree, validatorsData.validators, [ ...Array(validatorsData.validators.length).keys(), ]) @@ -338,7 +338,7 @@ describe('EthGenesisVault', () => { await setBalance(vaultAddr, 0n) await setBalance(poolEscrowAddr, assets + vaultBalance + poolEscrowBalance) - const tx = await depositDataManager + const tx = await depositDataRegistry .connect(admin) .registerValidators(vaultAddr, approveParams, indexes, proof.proofFlags, proof.proof) await expect(tx) diff --git a/test/EthPrivErc20Vault.spec.ts b/test/EthPrivErc20Vault.spec.ts index 1357f15f..ab615cf8 100644 --- a/test/EthPrivErc20Vault.spec.ts +++ b/test/EthPrivErc20Vault.spec.ts @@ -6,7 +6,7 @@ import { IKeeperRewards, Keeper, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { createDepositorMock, ethVaultFixture } from './shared/fixtures' @@ -28,7 +28,7 @@ describe('EthPrivErc20Vault', () => { keeper: Keeper, validatorsRegistry: Contract, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createPrivateVault: ThenArg>['createEthPrivErc20Vault'] @@ -39,7 +39,7 @@ describe('EthPrivErc20Vault', () => { keeper, validatorsRegistry, osTokenVaultController, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -74,7 +74,7 @@ describe('EthPrivErc20Vault', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const vaultReward = ethers.parseEther('1') const tree = await updateRewards(keeper, [ { reward: vaultReward, unlockedMevReward: 0n, vault: await vault.getAddress() }, @@ -191,7 +191,7 @@ describe('EthPrivErc20Vault', () => { beforeEach(async () => { await vault.connect(admin).updateWhitelist(sender.address, true) await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) }) diff --git a/test/EthPrivVault.spec.ts b/test/EthPrivVault.spec.ts index c0d46ecf..ffd1231d 100644 --- a/test/EthPrivVault.spec.ts +++ b/test/EthPrivVault.spec.ts @@ -5,7 +5,7 @@ import { EthPrivVault, Keeper, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -24,7 +24,7 @@ describe('EthPrivVault', () => { keeper: Keeper, validatorsRegistry: Contract, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry beforeEach('deploy fixtures', async () => { ;[sender, admin, other] = await (ethers as any).getSigners() @@ -38,7 +38,7 @@ describe('EthPrivVault', () => { keeper = fixture.keeper validatorsRegistry = fixture.validatorsRegistry osTokenVaultController = fixture.osTokenVaultController - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry }) it('has id', async () => { @@ -62,7 +62,7 @@ describe('EthPrivVault', () => { beforeEach(async () => { await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(admin).updateWhitelist(sender.address, true) await vault.connect(sender).deposit(sender.address, referrer, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) diff --git a/test/EthVault.burn.spec.ts b/test/EthVault.burn.spec.ts index 4be174d9..50d26c41 100644 --- a/test/EthVault.burn.spec.ts +++ b/test/EthVault.burn.spec.ts @@ -6,7 +6,7 @@ import { Keeper, OsTokenVaultController, OsToken, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -31,7 +31,7 @@ describe('EthVault - burn', () => { osTokenVaultController: OsTokenVaultController, osToken: OsToken, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] @@ -43,13 +43,13 @@ describe('EthVault - burn', () => { validatorsRegistry, osToken, osTokenVaultController, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) // collateralize vault - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(sender).deposit(sender.address, ZERO_ADDRESS, { value: assets }) osTokenShares = await osTokenVaultController.convertToShares(osTokenAssets) await vault.connect(sender).mintOsToken(sender.address, osTokenShares, ZERO_ADDRESS) diff --git a/test/EthVault.deposit.spec.ts b/test/EthVault.deposit.spec.ts index 39fc11b1..f6f30db3 100644 --- a/test/EthVault.deposit.spec.ts +++ b/test/EthVault.deposit.spec.ts @@ -7,7 +7,7 @@ import { IKeeperRewards, Keeper, SharedMevEscrow, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -30,7 +30,7 @@ describe('EthVault - deposit', () => { keeper: Keeper, mevEscrow: SharedMevEscrow, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] @@ -43,7 +43,7 @@ describe('EthVault - deposit', () => { keeper, validatorsRegistry, sharedMevEscrow: mevEscrow, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault( admin, @@ -127,7 +127,7 @@ describe('EthVault - deposit', () => { }) it('fails when not harvested', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await updateRewards(keeper, [ { reward: ethers.parseEther('5'), @@ -153,7 +153,7 @@ describe('EthVault - deposit', () => { await vault .connect(other) .deposit(other.address, referrer, { value: ethers.parseEther('32') }) - await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) + await registerEthValidator(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault.connect(other).enterExitQueue(ethers.parseEther('32'), other.address) let vaultReward = ethers.parseEther('10') diff --git a/test/EthVault.liquidate.spec.ts b/test/EthVault.liquidate.spec.ts index 59bfb945..0c7e2390 100644 --- a/test/EthVault.liquidate.spec.ts +++ b/test/EthVault.liquidate.spec.ts @@ -7,7 +7,7 @@ import { OsToken, OsTokenConfig, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' @@ -42,7 +42,7 @@ describe('EthVault - liquidate', () => { osToken: OsToken, osTokenConfig: OsTokenConfig, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] @@ -55,14 +55,14 @@ describe('EthVault - liquidate', () => { osTokenVaultController, osToken, osTokenConfig, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) await osTokenVaultController.connect(dao).setFeePercent(0) // collateralize vault - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const tx = await vault.connect(owner).deposit(owner.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) diff --git a/test/EthVault.mint.spec.ts b/test/EthVault.mint.spec.ts index 0548f90c..b9acb607 100644 --- a/test/EthVault.mint.spec.ts +++ b/test/EthVault.mint.spec.ts @@ -7,7 +7,7 @@ import { OsToken, VaultsRegistry, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -38,7 +38,7 @@ describe('EthVault - mint', () => { osTokenVaultController: OsTokenVaultController, osToken: OsToken, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] @@ -51,13 +51,13 @@ describe('EthVault - mint', () => { osToken, osTokenVaultController, vaultsRegistry, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) // collateralize vault - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const tx = await vault.connect(sender).deposit(sender.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) diff --git a/test/EthVault.multicall.spec.ts b/test/EthVault.multicall.spec.ts index 20363457..8f6656a1 100644 --- a/test/EthVault.multicall.spec.ts +++ b/test/EthVault.multicall.spec.ts @@ -7,7 +7,7 @@ import { Keeper, MulticallMock, OwnMevEscrow__factory, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -39,7 +39,7 @@ describe('EthVault - multicall', () => { let vault: EthVault, keeper: Keeper, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] @@ -49,7 +49,7 @@ describe('EthVault - multicall', () => { createEthVault: createVault, keeper, validatorsRegistry, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault( admin, @@ -71,7 +71,7 @@ describe('EthVault - multicall', () => { await vault .connect(sender) .deposit(sender.address, referrer, { value: ethers.parseEther('32') }) - await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) + await registerEthValidator(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await setBalance(await mevEscrow.getAddress(), ethers.parseEther('10')) const userShares = await vault.getShares(sender.address) @@ -169,7 +169,7 @@ describe('EthVault - multicall', () => { it('fails to deposit, enter exit queue, update state and claim in one transaction', async () => { const vaultAddr = await vault.getAddress() - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) expect(await vault.isStateUpdateRequired()).to.eq(false) expect(await keeper.canHarvest(vaultAddr)).to.eq(false) diff --git a/test/EthVault.redeem.spec.ts b/test/EthVault.redeem.spec.ts index 2c86660f..444b1f95 100644 --- a/test/EthVault.redeem.spec.ts +++ b/test/EthVault.redeem.spec.ts @@ -8,7 +8,7 @@ import { OsToken, OsTokenConfig, OsTokenVaultController, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' @@ -53,7 +53,7 @@ describe('EthVault - redeem osToken', () => { osToken: OsToken, osTokenConfig: OsTokenConfig, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] @@ -66,14 +66,14 @@ describe('EthVault - redeem osToken', () => { osTokenVaultController, osToken, osTokenConfig, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) await osTokenVaultController.connect(dao).setFeePercent(0) // collateralize vault - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const tx = await vault.connect(owner).deposit(owner.address, ZERO_ADDRESS, { value: assets }) shares = await extractDepositShares(tx) diff --git a/test/EthVault.settings.spec.ts b/test/EthVault.settings.spec.ts index 2318ae55..5e2f1272 100644 --- a/test/EthVault.settings.spec.ts +++ b/test/EthVault.settings.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat' import { Contract, Wallet } from 'ethers' -import { EthVault, Keeper, DepositDataManager } from '../typechain-types' +import { EthVault, Keeper, DepositDataRegistry } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -17,7 +17,7 @@ describe('EthVault - settings', () => { let createVault: ThenArg>['createEthVault'] let admin: Wallet, validatorsManager: Wallet, other: Wallet, newFeeRecipient: Wallet - let keeper: Keeper, validatorsRegistry: Contract, depositDataManager: DepositDataManager + let keeper: Keeper, validatorsRegistry: Contract, depositDataRegistry: DepositDataRegistry before('create fixture loader', async () => { ;[admin, validatorsManager, other, newFeeRecipient] = ( @@ -29,7 +29,7 @@ describe('EthVault - settings', () => { ;({ keeper, validatorsRegistry, - depositDataManager, + depositDataRegistry, createEthVault: createVault, } = await loadFixture(ethVaultFixture)) }) @@ -85,7 +85,7 @@ describe('EthVault - settings', () => { it('can be updated by admin', async () => { // initially equals to admin - expect(await vault.validatorsManager()).to.be.eq(await depositDataManager.getAddress()) + expect(await vault.validatorsManager()).to.be.eq(await depositDataRegistry.getAddress()) const receipt = await vault.connect(admin).setValidatorsManager(validatorsManager.address) await expect(receipt) .to.emit(vault, 'ValidatorsManagerUpdated') @@ -109,7 +109,7 @@ describe('EthVault - settings', () => { false, true ) - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) }) it('only admin can update', async () => { diff --git a/test/EthVault.state.spec.ts b/test/EthVault.state.spec.ts index fa059bc0..db092766 100644 --- a/test/EthVault.state.spec.ts +++ b/test/EthVault.state.spec.ts @@ -9,7 +9,7 @@ import { VaultsRegistry, OsTokenVaultController, OsTokenConfig, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import snapshotGasCost from './shared/snapshotGasCost' @@ -46,7 +46,7 @@ describe('EthVault - state', () => { vaultsRegistry: VaultsRegistry, osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createVault: ThenArg>['createEthVault'] let createVaultMock: ThenArg>['createEthVaultMock'] @@ -62,7 +62,7 @@ describe('EthVault - state', () => { vaultsRegistry, osTokenVaultController, osTokenConfig, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createVault(admin, { capacity, @@ -141,7 +141,7 @@ describe('EthVault - state', () => { ) const securityDeposit = 1000000000n await vault.connect(other).deposit(other.address, ZERO_ADDRESS, { value: 1 }) - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await vault._setTotalAssets(1) expect(await vault.totalAssets()).to.eq(1) expect(await vault.totalShares()).to.eq(securityDeposit + 1n) diff --git a/test/EthVault.upgrade.spec.ts b/test/EthVault.upgrade.spec.ts index 360323ec..dffb9a97 100644 --- a/test/EthVault.upgrade.spec.ts +++ b/test/EthVault.upgrade.spec.ts @@ -2,7 +2,7 @@ import { ethers } from 'hardhat' import { Contract, parseEther, Signer, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' import { - DepositDataManager, + DepositDataRegistry, EthVault, EthVault__factory, EthVaultFactory, @@ -52,7 +52,7 @@ describe('EthVault - upgrade', () => { sharedMevEscrow: SharedMevEscrow, osTokenConfig: OsTokenConfig, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, ethVaultFactory: EthVaultFactory, ethPrivVaultFactory: EthVaultFactory, ethErc20VaultFactory: EthVaultFactory, @@ -73,7 +73,7 @@ describe('EthVault - upgrade', () => { sharedMevEscrow = fixture.sharedMevEscrow osTokenConfig = fixture.osTokenConfig osTokenVaultController = fixture.osTokenVaultController - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry ethVaultFactory = fixture.ethVaultFactory ethPrivVaultFactory = fixture.ethPrivVaultFactory ethErc20VaultFactory = fixture.ethErc20VaultFactory @@ -94,7 +94,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, - fixture.depositDataManager, + fixture.depositDataRegistry, EXITING_ASSETS_MIN_DELAY ) currImpl = await vault.implementation() @@ -144,7 +144,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, - fixture.depositDataManager, + fixture.depositDataRegistry, EXITING_ASSETS_MIN_DELAY ) callData = ethers.AbiCoder.defaultAbiCoder().encode(['uint128'], [100]) @@ -164,7 +164,7 @@ describe('EthVault - upgrade', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, - fixture.depositDataManager, + fixture.depositDataRegistry, EXITING_ASSETS_MIN_DELAY ) callData = ethers.AbiCoder.defaultAbiCoder().encode(['uint128'], [100]) @@ -287,12 +287,12 @@ describe('EthVault - upgrade', () => { expect(await vaultV2.getShares(other.address)).to.be.eq(userShares) expect(await vaultV2.convertToAssets(userShares)).to.be.deep.eq(userAssets) expect(await vaultV2.osTokenPositions(other.address)).to.be.above(osTokenPosition) - expect(await vaultV2.validatorsManager()).to.be.eq(await depositDataManager.getAddress()) + expect(await vaultV2.validatorsManager()).to.be.eq(await depositDataRegistry.getAddress()) expect(await vaultV2.mevEscrow()).to.be.eq(mevEscrow) expect(await vaultV2.totalAssets()).to.be.eq(totalAssets) expect(await vaultV2.totalShares()).to.be.eq(totalShares) - expect(await depositDataManager.depositDataIndexes(vaultAddress)).to.be.eq(validatorIndex) - expect(await depositDataManager.depositDataRoots(vaultAddress)).to.be.eq(validatorsRoot) + expect(await depositDataRegistry.depositDataIndexes(vaultAddress)).to.be.eq(validatorIndex) + expect(await depositDataRegistry.depositDataRoots(vaultAddress)).to.be.eq(validatorsRoot) await snapshotGasCost(receipt) } await checkVault(vaults[0], await ethVaultFactory.implementation()) diff --git a/test/EthVault.whitelist.spec.ts b/test/EthVault.whitelist.spec.ts index 98842a3a..4cda9105 100644 --- a/test/EthVault.whitelist.spec.ts +++ b/test/EthVault.whitelist.spec.ts @@ -25,7 +25,7 @@ describe('EthVault - whitelist', () => { let vault: EthPrivVault, keeper: Keeper, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let createPrivateVault: ThenArg>['createEthPrivVault'] @@ -38,7 +38,7 @@ describe('EthVault - whitelist', () => { createEthPrivVault: createPrivateVault, keeper, validatorsRegistry, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -118,7 +118,7 @@ describe('EthVault - whitelist', () => { }) it('cannot update state and call', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) const tree = await updateRewards(keeper, [vaultReward]) diff --git a/test/KeeperRewards.spec.ts b/test/KeeperRewards.spec.ts index 1764d33f..4b7b4f2c 100644 --- a/test/KeeperRewards.spec.ts +++ b/test/KeeperRewards.spec.ts @@ -7,7 +7,7 @@ import { Keeper, OsTokenVaultController, SharedMevEscrow, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' @@ -42,7 +42,7 @@ describe('KeeperRewards', () => { validatorsRegistry: Contract, sharedMevEscrow: SharedMevEscrow, osTokenVaultController: OsTokenVaultController, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let globalRewardsNonce: number beforeEach(async () => { @@ -53,7 +53,7 @@ describe('KeeperRewards', () => { validatorsRegistry, sharedMevEscrow, osTokenVaultController, - depositDataManager, + depositDataRegistry, } = await loadFixture(ethVaultFixture)) await setBalance(oracle.address, ethers.parseEther('10000')) }) @@ -293,7 +293,7 @@ describe('KeeperRewards', () => { await vault .connect(admin) .deposit(await admin.getAddress(), ZERO_ADDRESS, { value: validatorDeposit }) - await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) + await registerEthValidator(vault, keeper, depositDataRegistry, admin, validatorsRegistry) expect(await keeper.isCollateralized(await vault.getAddress())).to.equal(true) expect(await keeper.canHarvest(await vault.getAddress())).to.equal(false) diff --git a/test/KeeperValidators.spec.ts b/test/KeeperValidators.spec.ts index 76ffd8e8..528b01e1 100644 --- a/test/KeeperValidators.spec.ts +++ b/test/KeeperValidators.spec.ts @@ -1,7 +1,7 @@ import { ethers } from 'hardhat' import { Contract, Wallet } from 'ethers' import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' -import { EthVault, IKeeperValidators, Keeper, DepositDataManager } from '../typechain-types' +import { EthVault, IKeeperValidators, Keeper, DepositDataRegistry } from '../typechain-types' import { ThenArg } from '../helpers/types' import { ethVaultFixture, getOraclesSignatures } from './shared/fixtures' import { expect } from './shared/expect' @@ -41,7 +41,7 @@ describe('KeeperValidators', () => { let keeper: Keeper, vault: EthVault, validatorsRegistry: Contract, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry let validatorsData: EthValidatorsData let validatorsRegistryRoot: string @@ -50,7 +50,7 @@ describe('KeeperValidators', () => { ;({ keeper, validatorsRegistry, - depositDataManager, + depositDataRegistry, createEthVault: createVault, } = await loadFixture(ethVaultFixture)) vault = await createVault( @@ -65,7 +65,7 @@ describe('KeeperValidators', () => { ) validatorsData = await createEthValidatorsData(vault) validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), validatorsData.root) }) @@ -114,13 +114,13 @@ describe('KeeperValidators', () => { { value: depositAmount } ) await expect( - depositDataManager.registerValidator(await vault.getAddress(), approveParams, proof) + depositDataRegistry.registerValidator(await vault.getAddress(), approveParams, proof) ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') }) it('fails for invalid signatures', async () => { await expect( - depositDataManager.registerValidator( + depositDataRegistry.registerValidator( await vault.getAddress(), { ...approveParams, @@ -133,7 +133,7 @@ describe('KeeperValidators', () => { it('fails for invalid deadline', async () => { await expect( - depositDataManager.registerValidator( + depositDataRegistry.registerValidator( await vault.getAddress(), { ...approveParams, @@ -146,7 +146,7 @@ describe('KeeperValidators', () => { it('fails for expired deadline', async () => { await expect( - depositDataManager.registerValidator( + depositDataRegistry.registerValidator( await vault.getAddress(), { ...approveParams, @@ -159,7 +159,7 @@ describe('KeeperValidators', () => { it('fails for invalid validator', async () => { await expect( - depositDataManager.registerValidator( + depositDataRegistry.registerValidator( await vault.getAddress(), { ...approveParams, @@ -172,7 +172,7 @@ describe('KeeperValidators', () => { it('fails for invalid proof', async () => { await expect( - depositDataManager.registerValidator( + depositDataRegistry.registerValidator( await vault.getAddress(), approveParams, getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) @@ -186,7 +186,7 @@ describe('KeeperValidators', () => { expect(rewards.assets).to.eq(0) const globalRewardsNonce = await keeper.rewardsNonce() - let receipt = await depositDataManager.registerValidator( + let receipt = await depositDataRegistry.registerValidator( await vault.getAddress(), approveParams, proof @@ -206,7 +206,7 @@ describe('KeeperValidators', () => { // fails to register twice await expect( - depositDataManager.registerValidator(await vault.getAddress(), approveParams, proof) + depositDataRegistry.registerValidator(await vault.getAddress(), approveParams, proof) ).revertedWithCustomError(keeper, 'InvalidValidatorsRegistryRoot') const newValidator = validatorsData.validators[1] @@ -223,7 +223,7 @@ describe('KeeperValidators', () => { newValidatorsRegistryRoot ) const newSignatures = getOraclesSignatures(newSigningData, ORACLES.length) - receipt = await depositDataManager.registerValidator( + receipt = await depositDataRegistry.registerValidator( await vault.getAddress(), { validatorsRegistryRoot: newValidatorsRegistryRoot, @@ -297,7 +297,7 @@ describe('KeeperValidators', () => { { value: depositAmount } ) await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), approveParams, indexes, @@ -309,7 +309,7 @@ describe('KeeperValidators', () => { it('fails for invalid signatures', async () => { await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { ...approveParams, @@ -324,7 +324,7 @@ describe('KeeperValidators', () => { it('fails for invalid validators', async () => { await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { ...approveParams, @@ -339,7 +339,7 @@ describe('KeeperValidators', () => { it('fails for invalid deadline', async () => { await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { ...approveParams, @@ -354,7 +354,7 @@ describe('KeeperValidators', () => { it('fails for expired deadline', async () => { await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { ...approveParams, @@ -371,7 +371,7 @@ describe('KeeperValidators', () => { const invalidProof = getValidatorsMultiProof(validatorsData.tree, [validators[0]], [0]) const exitSignaturesIpfsHash = approveParams.exitSignaturesIpfsHash as string await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), { validatorsRegistryRoot, @@ -404,7 +404,7 @@ describe('KeeperValidators', () => { const validatorsConcat = Buffer.concat(validators) const globalRewardsNonce = await keeper.rewardsNonce() - let receipt = await depositDataManager.registerValidators( + let receipt = await depositDataRegistry.registerValidators( await vault.getAddress(), approveParams, indexes, @@ -425,7 +425,7 @@ describe('KeeperValidators', () => { // fails to register twice await expect( - depositDataManager.registerValidators( + depositDataRegistry.registerValidators( await vault.getAddress(), approveParams, indexes, @@ -439,10 +439,10 @@ describe('KeeperValidators', () => { .deposit(sender.address, referrer, { value: depositAmount * BigInt(validators.length) }) // reset validator index - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), ZERO_BYTES32) - await depositDataManager + await depositDataRegistry .connect(admin) .setDepositDataRoot(await vault.getAddress(), validatorsData.root) const newSigningData = await getEthValidatorsSigningData( @@ -454,7 +454,7 @@ describe('KeeperValidators', () => { newValidatorsRegistryRoot ) const newSignatures = getOraclesSignatures(newSigningData, ORACLES.length) - receipt = await depositDataManager.registerValidators( + receipt = await depositDataRegistry.registerValidators( await vault.getAddress(), { validatorsRegistryRoot: newValidatorsRegistryRoot, @@ -519,7 +519,7 @@ describe('KeeperValidators', () => { }) it('fails for invalid signatures', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await expect( keeper.updateExitSignatures( await vault.getAddress(), @@ -531,7 +531,7 @@ describe('KeeperValidators', () => { }) it('fails for invalid deadline', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await expect( keeper.updateExitSignatures( await vault.getAddress(), @@ -543,7 +543,7 @@ describe('KeeperValidators', () => { }) it('fails for expired deadline', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const newDeadline = await getLatestBlockTimestamp() const newSigningData = await getEthValidatorsExitSignaturesSigningData( keeper, @@ -563,7 +563,7 @@ describe('KeeperValidators', () => { }) it('fails to submit update twice', async () => { - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) await keeper.updateExitSignatures( await vault.getAddress(), deadline, @@ -585,7 +585,7 @@ describe('KeeperValidators', () => { const nonce = await keeper.exitSignaturesNonces(await vault.getAddress()) expect(nonce).to.eq(0) - await collateralizeEthVault(vault, keeper, depositDataManager, admin, validatorsRegistry) + await collateralizeEthVault(vault, keeper, depositDataRegistry, admin, validatorsRegistry) const receipt = await keeper .connect(sender) diff --git a/test/OsToken.spec.ts b/test/OsToken.spec.ts index c568243f..9b3d5c64 100644 --- a/test/OsToken.spec.ts +++ b/test/OsToken.spec.ts @@ -6,7 +6,7 @@ import { OsToken, EthVault, Keeper, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { ethVaultFixture } from './shared/fixtures' @@ -38,7 +38,7 @@ describe('OsToken', () => { osToken: OsToken, vault: EthVault, keeper: Keeper, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry before('create fixture loader', async () => { ;[dao, initialHolder, admin, spender, recipient] = await (ethers as any).getSigners() @@ -54,7 +54,7 @@ describe('OsToken', () => { osTokenVaultController = fixture.osTokenVaultController keeper = fixture.keeper osToken = fixture.osToken - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry vault = await fixture.createEthVault(admin, vaultParams) admin = await ethers.getImpersonatedSigner(await vault.admin()) @@ -63,7 +63,7 @@ describe('OsToken', () => { await collateralizeEthVault( vault, fixture.keeper, - depositDataManager, + depositDataRegistry, admin, fixture.validatorsRegistry ) diff --git a/test/PriceFeed.test.ts b/test/PriceFeed.test.ts index bda6a6fb..9ff6ed3d 100644 --- a/test/PriceFeed.test.ts +++ b/test/PriceFeed.test.ts @@ -6,7 +6,7 @@ import { IKeeperRewards, OsTokenVaultController, PriceFeed, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { expect } from './shared/expect' import { createPriceFeed, ethVaultFixture } from './shared/fixtures' @@ -34,7 +34,7 @@ describe('PriceFeed', () => { let osTokenVaultController: OsTokenVaultController, priceFeed: PriceFeed, vault: EthVault, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry before('create fixture loader', async () => { ;[sender, dao, admin] = await (ethers as any).getSigners() @@ -46,14 +46,14 @@ describe('PriceFeed', () => { admin = await ethers.getImpersonatedSigner(await vault.admin()) osTokenVaultController = fixture.osTokenVaultController - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry priceFeed = await createPriceFeed(osTokenVaultController, description) // collateralize vault await collateralizeEthVault( vault, fixture.keeper, - depositDataManager, + depositDataRegistry, admin, fixture.validatorsRegistry ) diff --git a/test/RewardSplitter.spec.ts b/test/RewardSplitter.spec.ts index 44b72ca2..111ab62d 100644 --- a/test/RewardSplitter.spec.ts +++ b/test/RewardSplitter.spec.ts @@ -7,7 +7,7 @@ import { Keeper, RewardSplitter, RewardSplitter__factory, - DepositDataManager, + DepositDataRegistry, } from '../typechain-types' import { createRewardSplitterFactory, ethVaultFixture } from './shared/fixtures' import { expect } from './shared/expect' @@ -21,7 +21,7 @@ describe('RewardSplitter', () => { keeper: Keeper, rewardSplitter: RewardSplitter, erc20Vault: EthErc20Vault, - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry before('create fixture loader', async () => { ;[admin, other] = (await (ethers as any).getSigners()).slice(1, 3) @@ -52,18 +52,18 @@ describe('RewardSplitter', () => { true ) keeper = fixture.keeper - depositDataManager = fixture.depositDataManager + depositDataRegistry = fixture.depositDataRegistry await collateralizeEthVault( vault, keeper, - depositDataManager, + depositDataRegistry, admin, fixture.validatorsRegistry ) await collateralizeEthVault( erc20Vault, keeper, - depositDataManager, + depositDataRegistry, admin, fixture.validatorsRegistry ) diff --git a/test/VaultsRegistry.spec.ts b/test/VaultsRegistry.spec.ts index cb96788f..5af32572 100644 --- a/test/VaultsRegistry.spec.ts +++ b/test/VaultsRegistry.spec.ts @@ -39,7 +39,7 @@ describe('VaultsRegistry', () => { fixture.osTokenVaultController, fixture.osTokenConfig, fixture.sharedMevEscrow, - fixture.depositDataManager, + fixture.depositDataRegistry, EXITING_ASSETS_MIN_DELAY ) }) diff --git a/test/__snapshots__/DepositDataManager.spec.ts.snap b/test/__snapshots__/DepositDataRegistry.spec.ts.snap similarity index 52% rename from test/__snapshots__/DepositDataManager.spec.ts.snap rename to test/__snapshots__/DepositDataRegistry.spec.ts.snap index ad84613d..6be13016 100644 --- a/test/__snapshots__/DepositDataManager.spec.ts.snap +++ b/test/__snapshots__/DepositDataRegistry.spec.ts.snap @@ -1,34 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DepositDataManager deposit data manager update succeeds 1`] = ` +exports[`DepositDataRegistry deposit data manager update succeeds 1`] = ` Object { "calldataByteLength": 68, "gasUsed": 63707, } `; -exports[`DepositDataManager deposit data root update success 1`] = ` +exports[`DepositDataRegistry deposit data root update success 1`] = ` Object { "calldataByteLength": 68, "gasUsed": 64505, } `; -exports[`DepositDataManager migrate succeeds 1`] = ` +exports[`DepositDataRegistry migrate succeeds 1`] = ` Object { "calldataByteLength": 100, "gasUsed": 142334, } `; -exports[`DepositDataManager multiple validators succeeds 1`] = ` +exports[`DepositDataRegistry multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3364, "gasUsed": 687523, } `; -exports[`DepositDataManager single validator succeeds 1`] = ` +exports[`DepositDataRegistry single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, "gasUsed": 333583, diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index 39da306b..0daa95b7 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -51,8 +51,8 @@ import { SharedMevEscrow__factory, VaultsRegistry, VaultsRegistry__factory, - DepositDataManager, - DepositDataManager__factory, + DepositDataRegistry, + DepositDataRegistry__factory, } from '../../typechain-types' import { getEthValidatorsRegistryFactory } from './contracts' import { @@ -241,13 +241,13 @@ export const createRewardSplitterFactory = async function (): Promise { +): Promise { const signer = await ethers.provider.getSigner() - const factory = await ethers.getContractFactory('DepositDataManager') + const factory = await ethers.getContractFactory('DepositDataRegistry') const contract = await factory.deploy(await vaultsRegistry.getAddress()) - return DepositDataManager__factory.connect(await contract.getAddress(), signer) + return DepositDataRegistry__factory.connect(await contract.getAddress(), signer) } export const createOsTokenVaultController = async function ( @@ -410,7 +410,7 @@ export const deployEthGenesisVaultImpl = async function ( osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, poolEscrow: PoolEscrowMock, rewardEthToken: LegacyRewardTokenMock ): Promise { @@ -422,7 +422,7 @@ export const deployEthGenesisVaultImpl = async function ( await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), - await depositDataManager.getAddress(), + await depositDataRegistry.getAddress(), await poolEscrow.getAddress(), await rewardEthToken.getAddress(), EXITING_ASSETS_MIN_DELAY, @@ -441,7 +441,7 @@ export const deployEthVaultImplementation = async function ( osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, exitingAssetsMinDelay: number ): Promise { const factory = await ethers.getContractFactory(vaultType) @@ -452,7 +452,7 @@ export const deployEthVaultImplementation = async function ( await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), - await depositDataManager.getAddress(), + await depositDataRegistry.getAddress(), exitingAssetsMinDelay, ] const contract = await factory.deploy(...constructorArgs) @@ -555,7 +555,7 @@ interface EthVaultFixture { vaultsRegistry: VaultsRegistry keeper: Keeper sharedMevEscrow: SharedMevEscrow - depositDataManager: DepositDataManager + depositDataRegistry: DepositDataRegistry validatorsRegistry: Contract ethVaultFactory: EthVaultFactory ethPrivVaultFactory: EthVaultFactory @@ -688,8 +688,8 @@ export const ethVaultFixture = async function (): Promise { OSTOKEN_LTV ) - // 7. deploy depositDataManager - const depositDataManager = await createDepositDataManager(vaultsRegistry) + // 7. deploy depositDataRegistry + const depositDataRegistry = await createDepositDataRegistry(vaultsRegistry) // 8. deploy implementations and factories const factories = {} @@ -712,7 +712,7 @@ export const ethVaultFixture = async function (): Promise { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, EXITING_ASSETS_MIN_DELAY ) await vaultsRegistry.addVaultImpl(vaultImpl) @@ -737,7 +737,7 @@ export const ethVaultFixture = async function (): Promise { return { vaultsRegistry, sharedMevEscrow, - depositDataManager, + depositDataRegistry, keeper, validatorsRegistry, ethVaultFactory, @@ -785,7 +785,7 @@ export const ethVaultFixture = async function (): Promise { await vaultsRegistry.getAddress(), await validatorsRegistry.getAddress(), await sharedMevEscrow.getAddress(), - await depositDataManager.getAddress(), + await depositDataRegistry.getAddress(), EXITING_ASSETS_MIN_DELAY, ] const contract = await factory.deploy(...constructorArgs) @@ -973,7 +973,7 @@ export const ethVaultFixture = async function (): Promise { osTokenVaultController, osTokenConfig, sharedMevEscrow, - depositDataManager, + depositDataRegistry, poolEscrow, rewardEthToken ) diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index 555f5c54..de3e7166 100644 --- a/test/shared/rewards.ts +++ b/test/shared/rewards.ts @@ -1,7 +1,7 @@ import { ethers, network } from 'hardhat' import { Contract, Signer } from 'ethers' import { StandardMerkleTree } from '@openzeppelin/merkle-tree' -import { EthVault, IKeeperRewards, Keeper, DepositDataManager } from '../../typechain-types' +import { EthVault, IKeeperRewards, Keeper, DepositDataRegistry } from '../../typechain-types' import { EIP712Domain, EXITING_ASSETS_MIN_DELAY, @@ -182,7 +182,7 @@ export async function collateralizeEthV1Vault( export async function collateralizeEthVault( vault: EthVaultType, keeper: Keeper, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, admin: Signer, validatorsRegistry: Contract ) { @@ -196,7 +196,7 @@ export async function collateralizeEthVault( .connect(admin) .deposit(adminAddr, ZERO_ADDRESS, { value: validatorDeposit }) const receivedShares = await extractDepositShares(tx) - await registerEthValidator(vault, keeper, depositDataManager, admin, validatorsRegistry) + await registerEthValidator(vault, keeper, depositDataRegistry, admin, validatorsRegistry) // exit validator const response = await vault.connect(admin).enterExitQueue(receivedShares, adminAddr) diff --git a/test/shared/validators.ts b/test/shared/validators.ts index d3323d32..667e52fd 100644 --- a/test/shared/validators.ts +++ b/test/shared/validators.ts @@ -4,7 +4,7 @@ import { ethers, network } from 'hardhat' import { Buffer } from 'buffer' import { BytesLike, Contract, ContractTransactionResponse, Signer } from 'ethers' import bls from 'bls-eth-wasm' -import { EthVault, Keeper, DepositDataManager } from '../../typechain-types' +import { EthVault, Keeper, DepositDataRegistry } from '../../typechain-types' import { EIP712Domain, KeeperUpdateExitSignaturesSig, @@ -285,7 +285,7 @@ export function getValidatorsMultiProof( export async function registerEthValidator( vault: EthVaultType, keeper: Keeper, - depositDataManager: DepositDataManager, + depositDataRegistry: DepositDataRegistry, admin: Signer, validatorsRegistry: Contract ): Promise { @@ -293,11 +293,11 @@ export async function registerEthValidator( const validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() const vaultAddress = await vault.getAddress() if ((await vault.version()) > 1) { - if ((await depositDataManager.depositDataRoots(vaultAddress)) != ZERO_BYTES32) { + if ((await depositDataRegistry.depositDataRoots(vaultAddress)) != ZERO_BYTES32) { // reset validator index - await depositDataManager.connect(admin).setDepositDataRoot(vaultAddress, ZERO_BYTES32) + await depositDataRegistry.connect(admin).setDepositDataRoot(vaultAddress, ZERO_BYTES32) } - await depositDataManager.connect(admin).setDepositDataRoot(vaultAddress, validatorsData.root) + await depositDataRegistry.connect(admin).setDepositDataRoot(vaultAddress, validatorsData.root) } else { await vault.connect(admin).setValidatorsRoot(validatorsData.root) } @@ -314,7 +314,7 @@ export async function registerEthValidator( const signatures = getOraclesSignatures(signingData, VALIDATORS_MIN_ORACLES) const proof = getValidatorProof(validatorsData.tree, validator, 0) if ((await vault.version()) > 1) { - return await depositDataManager.connect(admin).registerValidator( + return await depositDataRegistry.connect(admin).registerValidator( vaultAddress, { validatorsRegistryRoot, From 3d601cb8b54be30b185e53ab9f1956d2fa3c1505 Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Tue, 2 Apr 2024 22:05:27 +0300 Subject: [PATCH 28/29] Make _withdrawalCredentials function private --- contracts/vaults/modules/VaultEthStaking.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/vaults/modules/VaultEthStaking.sol b/contracts/vaults/modules/VaultEthStaking.sol index 41968612..e593dfa9 100644 --- a/contracts/vaults/modules/VaultEthStaking.sol +++ b/contracts/vaults/modules/VaultEthStaking.sol @@ -129,7 +129,7 @@ abstract contract VaultEthStaking is * @dev Internal function for calculating Vault withdrawal credentials * @return The credentials used for the validators withdrawals */ - function _withdrawalCredentials() internal view virtual returns (bytes memory) { + function _withdrawalCredentials() private view returns (bytes memory) { return abi.encodePacked(bytes1(0x01), bytes11(0x0), address(this)); } From 939a39f36a57eec4279b714b7dff001d668fbdcf Mon Sep 17 00:00:00 2001 From: Dmitri Tsumak Date: Wed, 3 Apr 2024 14:22:25 +0300 Subject: [PATCH 29/29] Add state update to DepositDataRegistry --- abi/IDepositDataRegistry.json | 40 +++++++++++++++++++ contracts/interfaces/IDepositDataRegistry.sol | 11 +++++ contracts/validators/DepositDataRegistry.sol | 10 +++++ test/DepositDataRegistry.spec.ts | 30 ++++++++++++++ .../DepositDataRegistry.spec.ts.snap | 17 +++++--- .../EthGenesisVault.spec.ts.snap | 4 +- .../EthVault.upgrade.spec.ts.snap | 10 ++--- .../KeeperValidators.spec.ts.snap | 8 ++-- 8 files changed, 114 insertions(+), 16 deletions(-) diff --git a/abi/IDepositDataRegistry.json b/abi/IDepositDataRegistry.json index acf349ad..dbc2a33a 100644 --- a/abi/IDepositDataRegistry.json +++ b/abi/IDepositDataRegistry.json @@ -312,5 +312,45 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "rewardsRoot", + "type": "bytes32" + }, + { + "internalType": "int160", + "name": "reward", + "type": "int160" + }, + { + "internalType": "uint160", + "name": "unlockedMevReward", + "type": "uint160" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "internalType": "struct IKeeperRewards.HarvestParams", + "name": "harvestParams", + "type": "tuple" + } + ], + "name": "updateVaultState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] diff --git a/contracts/interfaces/IDepositDataRegistry.sol b/contracts/interfaces/IDepositDataRegistry.sol index f3498669..90b05d1f 100644 --- a/contracts/interfaces/IDepositDataRegistry.sol +++ b/contracts/interfaces/IDepositDataRegistry.sol @@ -3,6 +3,7 @@ pragma solidity =0.8.22; import {IKeeperValidators} from './IKeeperValidators.sol'; +import {IKeeperRewards} from './IKeeperRewards.sol'; import {IMulticall} from './IMulticall.sol'; /** @@ -74,6 +75,16 @@ interface IDepositDataRegistry is IMulticall { */ function setDepositDataRoot(address vault, bytes32 depositDataRoot) external; + /** + * @notice Updates the vault state. Can be used in multicall to update state and register validator(s). + * @param vault The address of the vault + * @param harvestParams The harvest params to use for updating the vault state + */ + function updateVaultState( + address vault, + IKeeperRewards.HarvestParams calldata harvestParams + ) external; + /** * @notice Function for registering single validator * @param vault The address of the vault diff --git a/contracts/validators/DepositDataRegistry.sol b/contracts/validators/DepositDataRegistry.sol index 986470fa..c341fae3 100644 --- a/contracts/validators/DepositDataRegistry.sol +++ b/contracts/validators/DepositDataRegistry.sol @@ -9,6 +9,8 @@ import {IVaultAdmin} from '../interfaces/IVaultAdmin.sol'; import {IVaultValidators} from '../interfaces/IVaultValidators.sol'; import {IVaultVersion} from '../interfaces/IVaultVersion.sol'; import {IVaultsRegistry} from '../interfaces/IVaultsRegistry.sol'; +import {IVaultState} from '../interfaces/IVaultState.sol'; +import {IKeeperRewards} from '../interfaces/IKeeperRewards.sol'; import {Errors} from '../libraries/Errors.sol'; import {Multicall} from '../base/Multicall.sol'; @@ -81,6 +83,14 @@ contract DepositDataRegistry is Multicall, IDepositDataRegistry { emit DepositDataRootUpdated(vault, depositDataRoot); } + /// @inheritdoc IDepositDataRegistry + function updateVaultState( + address vault, + IKeeperRewards.HarvestParams calldata harvestParams + ) external override { + IVaultState(vault).updateState(harvestParams); + } + /// @inheritdoc IDepositDataRegistry function registerValidator( address vault, diff --git a/test/DepositDataRegistry.spec.ts b/test/DepositDataRegistry.spec.ts index acba758b..b81fc3fd 100644 --- a/test/DepositDataRegistry.spec.ts +++ b/test/DepositDataRegistry.spec.ts @@ -8,6 +8,7 @@ import { IKeeperValidators, Keeper, VaultsRegistry, + IKeeperRewards, } from '../typechain-types' import snapshotGasCost from './shared/snapshotGasCost' import { expect } from './shared/expect' @@ -37,6 +38,7 @@ import { ZERO_BYTES32, } from './shared/constants' import { getEthVaultV1Factory } from './shared/contracts' +import { getHarvestParams, getRewardsRootProof, updateRewards } from './shared/rewards' const gwei = 1000000000n const uintSerializer = new UintNumberType(8) @@ -231,6 +233,34 @@ describe('DepositDataRegistry', () => { ).to.be.revertedWithCustomError(depositDataRegistry, 'InvalidProof') }) + it('can update state and register validator', async () => { + const vaultAddress = await vault.getAddress() + const vaultReward = getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), 0n) + const tree = await updateRewards(keeper, [vaultReward]) + const harvestParams: IKeeperRewards.HarvestParamsStruct = { + rewardsRoot: tree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof: getRewardsRootProof(tree, vaultReward), + } + + const calls: string[] = [ + depositDataRegistry.interface.encodeFunctionData('updateVaultState', [ + vaultAddress, + harvestParams, + ]), + depositDataRegistry.interface.encodeFunctionData('registerValidator', [ + vaultAddress, + approvalParams, + proof, + ]), + ] + const receipt = await depositDataRegistry.multicall(calls) + const publicKey = `0x${validator.subarray(0, 48).toString('hex')}` + await expect(receipt).to.emit(vault, 'ValidatorRegistered').withArgs(publicKey) + await snapshotGasCost(receipt) + }) + it('succeeds', async () => { const index = await validatorsRegistry.get_deposit_count() const receipt = await depositDataRegistry.registerValidator( diff --git a/test/__snapshots__/DepositDataRegistry.spec.ts.snap b/test/__snapshots__/DepositDataRegistry.spec.ts.snap index 6be13016..8c2e7eb6 100644 --- a/test/__snapshots__/DepositDataRegistry.spec.ts.snap +++ b/test/__snapshots__/DepositDataRegistry.spec.ts.snap @@ -3,34 +3,41 @@ exports[`DepositDataRegistry deposit data manager update succeeds 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 63707, + "gasUsed": 63743, } `; exports[`DepositDataRegistry deposit data root update success 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 64505, + "gasUsed": 64551, } `; exports[`DepositDataRegistry migrate succeeds 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 142334, + "gasUsed": 142380, } `; exports[`DepositDataRegistry multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3364, - "gasUsed": 687523, + "gasUsed": 688109, +} +`; + +exports[`DepositDataRegistry single validator can update state and register validator 1`] = ` +Object { + "calldataByteLength": 1636, + "gasUsed": 407165, } `; exports[`DepositDataRegistry single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 333583, + "gasUsed": 333737, } `; diff --git a/test/__snapshots__/EthGenesisVault.spec.ts.snap b/test/__snapshots__/EthGenesisVault.spec.ts.snap index 1695a7f2..0a0a1cc1 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -24,14 +24,14 @@ Object { exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 651991, + "gasUsed": 652577, } `; exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 311841, + "gasUsed": 311995, } `; diff --git a/test/__snapshots__/EthVault.upgrade.spec.ts.snap b/test/__snapshots__/EthVault.upgrade.spec.ts.snap index d917c4a1..8ae7619f 100644 --- a/test/__snapshots__/EthVault.upgrade.spec.ts.snap +++ b/test/__snapshots__/EthVault.upgrade.spec.ts.snap @@ -3,35 +3,35 @@ exports[`EthVault - upgrade does not modify the state variables 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164393, + "gasUsed": 164439, } `; exports[`EthVault - upgrade does not modify the state variables 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 165201, + "gasUsed": 165247, } `; exports[`EthVault - upgrade does not modify the state variables 3`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164669, + "gasUsed": 164715, } `; exports[`EthVault - upgrade does not modify the state variables 4`] = ` Object { "calldataByteLength": 100, - "gasUsed": 165465, + "gasUsed": 165511, } `; exports[`EthVault - upgrade does not modify the state variables 5`] = ` Object { "calldataByteLength": 100, - "gasUsed": 164489, + "gasUsed": 164535, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index c4199fc6..eeedb497 100644 --- a/test/__snapshots__/KeeperValidators.spec.ts.snap +++ b/test/__snapshots__/KeeperValidators.spec.ts.snap @@ -3,28 +3,28 @@ exports[`KeeperValidators register multiple validators succeeds 1`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 693928, + "gasUsed": 694514, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3748, - "gasUsed": 602172, + "gasUsed": 602758, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 340009, + "gasUsed": 340163, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 286284, + "gasUsed": 286438, } `;