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/.openzeppelin/unknown-10200.json b/.openzeppelin/unknown-10200.json new file mode 100644 index 00000000..abe17534 --- /dev/null +++ b/.openzeppelin/unknown-10200.json @@ -0,0 +1,3379 @@ +{ + "manifestVersion": "3.2", + "proxies": [], + "impls": { + "67568a59cb8fef8f6f9ada63a1644474e9a1ac99fffccba9fb30a7e58eb70fc2": { + "address": "0x4f0F98ddA4c17705d5176BFF0cC5ED087888F672", + "layout": { + "solcVersion": "0.8.22", + "storage": [], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "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(Ownable2StepStorage)14_storage": { + "label": "struct Ownable2StepUpgradeable.Ownable2StepStorage", + "members": [ + { + "label": "_pendingOwner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)55_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable2Step": [ + { + "contract": "Ownable2StepUpgradeable", + "label": "_pendingOwner", + "type": "t_address", + "src": "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol:23", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:24", + "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" + } + ] + } + } + }, + "c21d82e77e26a5ba88d9ab135f545e54e93cc6d941f087f0bf5041ff8abec329": { + "address": "0x760eB7070E46abB81282EE2818584E8446Aaa18a", + "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": "_xdaiManager", + "offset": 0, + "slot": "413", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "414", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "464", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoVault", + "src": "contracts/vaults/gnosis/GnoVault.sol:135" + } + ], + "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" + } + ] + } + } + }, + "77a4447f76dca11184ed34803b5fa740565809d78d79996e94911ca42bd9afd5": { + "address": "0x377fdD92A3Dab4C119813674fcd1C6855f541beB", + "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": "_xdaiManager", + "offset": 0, + "slot": "413", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "414", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "464", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoVault", + "src": "contracts/vaults/gnosis/GnoVault.sol:135" + }, + { + "label": "whitelister", + "offset": 0, + "slot": "514", + "type": "t_address", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:17" + }, + { + "label": "whitelistedAccounts", + "offset": 0, + "slot": "515", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "516", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "566", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoPrivVault", + "src": "contracts/vaults/gnosis/GnoPrivVault.sol:113" + } + ], + "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" + } + ] + } + } + }, + "a2c23a2fdf068b05211b0279577f9ebb8b8f56c4e6afa7424bc3f761f366cdac": { + "address": "0xfFA972eaB69Ce6e68f02372Faccac8393D90e193", + "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": "_xdaiManager", + "offset": 0, + "slot": "518", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "519", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "569", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoErc20Vault", + "src": "contracts/vaults/gnosis/GnoErc20Vault.sol:187" + } + ], + "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" + } + ] + } + } + }, + "94a382ed78b6960bafe1b1e5296c03c39a89b205053f5e66da921088b108bf40": { + "address": "0x150c4F8E072831ACF3151f1Ed873d510994E21c1", + "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": "_xdaiManager", + "offset": 0, + "slot": "413", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "414", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "464", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoVault", + "src": "contracts/vaults/gnosis/GnoVault.sol:135" + }, + { + "label": "blocklistManager", + "offset": 0, + "slot": "514", + "type": "t_address", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:17" + }, + { + "label": "blockedAccounts", + "offset": 0, + "slot": "515", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "516", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "566", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoBlocklistVault", + "src": "contracts/vaults/gnosis/GnoBlocklistVault.sol:113" + } + ], + "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" + } + ] + } + } + }, + "6b6e927c4b18fe8a724e199c93a2cbdb7931303591644a71007d069c0da992e5": { + "address": "0xA28444f410f8332879E18447CEeAfD3a76145164", + "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": "_xdaiManager", + "offset": 0, + "slot": "518", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "519", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "569", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoErc20Vault", + "src": "contracts/vaults/gnosis/GnoErc20Vault.sol:187" + }, + { + "label": "whitelister", + "offset": 0, + "slot": "619", + "type": "t_address", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:17" + }, + { + "label": "whitelistedAccounts", + "offset": 0, + "slot": "620", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "621", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultWhitelist", + "src": "contracts/vaults/modules/VaultWhitelist.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "671", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoPrivErc20Vault", + "src": "contracts/vaults/gnosis/GnoPrivErc20Vault.sol:121" + } + ], + "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" + } + ] + } + } + }, + "0462d921a59986b9e45c01e18b030374014963b407bb83cf7c155fb13cfd26af": { + "address": "0x7905b6735e26b309b366A6Aa2BD24934dEfB6953", + "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": "_xdaiManager", + "offset": 0, + "slot": "518", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "519", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "569", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoErc20Vault", + "src": "contracts/vaults/gnosis/GnoErc20Vault.sol:187" + }, + { + "label": "blocklistManager", + "offset": 0, + "slot": "619", + "type": "t_address", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:17" + }, + { + "label": "blockedAccounts", + "offset": 0, + "slot": "620", + "type": "t_mapping(t_address,t_bool)", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "621", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultBlocklist", + "src": "contracts/vaults/modules/VaultBlocklist.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "671", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoBlocklistErc20Vault", + "src": "contracts/vaults/gnosis/GnoBlocklistErc20Vault.sol:126" + } + ], + "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" + } + ] + } + } + }, + "3eb8d69a103523a091802e253a715e016ae0a3ec4b97ee534660370627e4c244": { + "address": "0xcD1814c23d8567fa7051995aeD23cD7D30Eef3BD", + "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": "_xdaiManager", + "offset": 0, + "slot": "413", + "type": "t_address", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:39" + }, + { + "label": "__gap", + "offset": 0, + "slot": "414", + "type": "t_array(t_uint256)50_storage", + "contract": "VaultGnoStaking", + "src": "contracts/vaults/modules/VaultGnoStaking.sol:224" + }, + { + "label": "__gap", + "offset": 0, + "slot": "464", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoVault", + "src": "contracts/vaults/gnosis/GnoVault.sol:135" + }, + { + "label": "__gap", + "offset": 0, + "slot": "514", + "type": "t_array(t_uint256)50_storage", + "contract": "GnoGenesisVault", + "src": "contracts/vaults/gnosis/GnoGenesisVault.sol:225" + } + ], + "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" + } + ] + } + } + } + } +} 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/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/IBalancerVault.json b/abi/IBalancerVault.json new file mode 100644 index 00000000..422eda57 --- /dev/null +++ b/abi/IBalancerVault.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "enum IBalancerVault.SwapKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "assetIn", + "type": "address" + }, + { + "internalType": "address", + "name": "assetOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "userData", + "type": "bytes" + } + ], + "internalType": "struct IBalancerVault.SingleSwap", + "name": "singleSwap", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bool", + "name": "fromInternalBalance", + "type": "bool" + }, + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bool", + "name": "toInternalBalance", + "type": "bool" + } + ], + "internalType": "struct IBalancerVault.FundManagement", + "name": "funds", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/abi/IEthBlocklistErc20Vault.json b/abi/IEthBlocklistErc20Vault.json new file mode 100644 index 00000000..072c01e1 --- /dev/null +++ b/abi/IEthBlocklistErc20Vault.json @@ -0,0 +1,1669 @@ +[ + { + "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": "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": 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": "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": [ + { + "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": "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": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "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..3c0d4df8 --- /dev/null +++ b/abi/IEthBlocklistVault.json @@ -0,0 +1,1372 @@ +[ + { + "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": "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": 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": "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": [ + { + "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": "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": "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..aa1ff233 100644 --- a/abi/IEthErc20Vault.json +++ b/abi/IEthErc20Vault.json @@ -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": [ @@ -648,23 +685,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" }, @@ -1094,30 +1115,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 +1316,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 c9a4b2b6..dad4d020 100644 --- a/abi/IEthFoxVault.json +++ b/abi/IEthFoxVault.json @@ -311,6 +311,62 @@ "name": "Redeemed", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": [ @@ -464,23 +520,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" }, @@ -764,30 +804,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": [ { @@ -966,6 +982,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..441f361b 100644 --- a/abi/IEthGenesisVault.json +++ b/abi/IEthGenesisVault.json @@ -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": [ @@ -581,23 +618,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" }, @@ -963,30 +984,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 +1172,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/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 0204abed..8c40441f 100644 --- a/abi/IEthPrivErc20Vault.json +++ b/abi/IEthPrivErc20Vault.json @@ -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": [ @@ -692,23 +729,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" }, @@ -1138,30 +1159,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 +1373,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..eba6fdc6 100644 --- a/abi/IEthPrivVault.json +++ b/abi/IEthPrivVault.json @@ -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": [ @@ -562,23 +599,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" }, @@ -920,30 +941,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 +1142,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..de74fcaa 100644 --- a/abi/IEthVault.json +++ b/abi/IEthVault.json @@ -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": [ @@ -518,23 +555,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" }, @@ -876,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": [ { @@ -1088,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/IGnoBlocklistErc20Vault.json b/abi/IGnoBlocklistErc20Vault.json new file mode 100644 index 00000000..f6e4a2f2 --- /dev/null +++ b/abi/IGnoBlocklistErc20Vault.json @@ -0,0 +1,1709 @@ +[ + { + "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": "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": 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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "address", + "name": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [], + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoBlocklistVault.json b/abi/IGnoBlocklistVault.json new file mode 100644 index 00000000..354d2443 --- /dev/null +++ b/abi/IGnoBlocklistVault.json @@ -0,0 +1,1412 @@ +[ + { + "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": "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": 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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": [ + { + "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": [ + { + "internalType": "address", + "name": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [], + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoErc20Vault.json b/abi/IGnoErc20Vault.json new file mode 100644 index 00000000..d6b9a40b --- /dev/null +++ b/abi/IGnoErc20Vault.json @@ -0,0 +1,1602 @@ +[ + { + "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": 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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "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": "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "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": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": [], + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoGenesisVault.json b/abi/IGnoGenesisVault.json new file mode 100644 index 00000000..cc2b5c4a --- /dev/null +++ b/abi/IGnoGenesisVault.json @@ -0,0 +1,1392 @@ +[ + { + "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": 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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "type": "event" + }, + { + "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": [], + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": [ + { + "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": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": [], + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoPoolEscrow.json b/abi/IGnoPoolEscrow.json new file mode 100644 index 00000000..640cf937 --- /dev/null +++ b/abi/IGnoPoolEscrow.json @@ -0,0 +1,152 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferApplied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "futureOwner", + "type": "address" + } + ], + "name": "OwnershipTransferCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [], + "name": "applyOwnershipTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "commitOwnershipTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "futureOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/abi/IGnoPrivErc20Vault.json b/abi/IGnoPrivErc20Vault.json new file mode 100644 index 00000000..514a6740 --- /dev/null +++ b/abi/IGnoPrivErc20Vault.json @@ -0,0 +1,1709 @@ +[ + { + "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": 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": "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": [ + { + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "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": "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "address", + "name": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateWhitelist", + "outputs": [], + "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", + "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": "account", + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoPrivVault.json b/abi/IGnoPrivVault.json new file mode 100644 index 00000000..d625ea06 --- /dev/null +++ b/abi/IGnoPrivVault.json @@ -0,0 +1,1412 @@ +[ + { + "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": 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": "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": [ + { + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "type": "event" + }, + { + "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": [], + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": [ + { + "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": [ + { + "internalType": "address", + "name": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateWhitelist", + "outputs": [], + "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", + "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": "account", + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoValidatorsRegistry.json b/abi/IGnoValidatorsRegistry.json new file mode 100644 index 00000000..d0dc1e63 --- /dev/null +++ b/abi/IGnoValidatorsRegistry.json @@ -0,0 +1,145 @@ +[ + { + "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": "pubkeys", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "withdrawal_credentials", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "deposit_data_roots", + "type": "bytes32[]" + } + ], + "name": "batchDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "claimWithdrawal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + }, + { + "internalType": "uint256", + "name": "stake_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "get_deposit_root", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "withdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoVault.json b/abi/IGnoVault.json new file mode 100644 index 00000000..d97c93c7 --- /dev/null +++ b/abi/IGnoVault.json @@ -0,0 +1,1305 @@ +[ + { + "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": 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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "type": "event" + }, + { + "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": [], + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "nonpayable", + "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": [ + { + "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": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": [], + "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" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IGnoVaultFactory.json b/abi/IGnoVaultFactory.json new file mode 100644 index 00000000..7f62a879 --- /dev/null +++ b/abi/IGnoVaultFactory.json @@ -0,0 +1,96 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "ownMevEscrow", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "params", + "type": "bytes" + } + ], + "name": "VaultCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "params", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isOwnMevEscrow", + "type": "bool" + } + ], + "name": "createVault", + "outputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ownMevEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IRewardGnoToken.json b/abi/IRewardGnoToken.json new file mode 100644 index 00000000..69183d1f --- /dev/null +++ b/abi/IRewardGnoToken.json @@ -0,0 +1,54 @@ +[ + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalPenalty", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRewards", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "rewardsDelta", + "type": "int256" + } + ], + "name": "updateTotalRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] 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..d513a237 100644 --- a/abi/IVaultEnterExit.json +++ b/abi/IVaultEnterExit.json @@ -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", @@ -300,23 +337,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" }, @@ -472,30 +493,6 @@ "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 +532,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..76ae7f82 100644 --- a/abi/IVaultEthStaking.json +++ b/abi/IVaultEthStaking.json @@ -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": [ @@ -351,23 +388,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" }, @@ -580,30 +601,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 +766,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/IVaultGnoStaking.json b/abi/IVaultGnoStaking.json new file mode 100644 index 00000000..c8007a8e --- /dev/null +++ b/abi/IVaultGnoStaking.json @@ -0,0 +1,947 @@ +[ + { + "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": 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": "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": "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": [ + { + "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": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "xdaiManager", + "type": "address" + } + ], + "name": "XdaiManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "name": "XdaiSwapped", + "type": "event" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "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": "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": [], + "name": "queuedShares", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "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": "xdaiManager_", + "type": "address" + } + ], + "name": "setXdaiManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swapXdaiToGno", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "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": [ + { + "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": [], + "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", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "xdaiManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/IVaultMev.json b/abi/IVaultMev.json index 7f267dbe..fedf4cbf 100644 --- a/abi/IVaultMev.json +++ b/abi/IVaultMev.json @@ -268,6 +268,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..c0f42b08 100644 --- a/abi/IVaultOsToken.json +++ b/abi/IVaultOsToken.json @@ -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", @@ -467,23 +504,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" }, @@ -710,30 +731,6 @@ "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 +793,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..53dc43c1 100644 --- a/abi/IVaultState.json +++ b/abi/IVaultState.json @@ -255,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/IVaultToken.json b/abi/IVaultToken.json index 6e4f52d7..a3e6bb4e 100644 --- a/abi/IVaultToken.json +++ b/abi/IVaultToken.json @@ -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", @@ -430,23 +467,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" }, @@ -690,30 +711,6 @@ "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 +763,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..9baee071 100644 --- a/abi/IVaultValidators.json +++ b/abi/IVaultValidators.json @@ -445,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/IXdaiExchange.json b/abi/IXdaiExchange.json new file mode 100644 index 00000000..0d85c6ef --- /dev/null +++ b/abi/IXdaiExchange.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "assets", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/chiado-config.json b/chiado-config.json new file mode 100644 index 00000000..069b56c3 --- /dev/null +++ b/chiado-config.json @@ -0,0 +1,6 @@ +[ + { + "public_key": "0x123..", + "exit_signature": "0x456..." + } +] diff --git a/contracts/interfaces/IBalancerVault.sol b/contracts/interfaces/IBalancerVault.sol new file mode 100644 index 00000000..af5fba9d --- /dev/null +++ b/contracts/interfaces/IBalancerVault.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +pragma solidity =0.8.22; + +/** + * @title IBalancerVault + * @author Balancer + * @notice Interface for the Balancer Vault contract + */ +interface IBalancerVault { + enum SwapKind { + GIVEN_IN, + GIVEN_OUT + } + + /** + * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on + * the `kind` value. + * + * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address). + * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault. + * + * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be + * used to extend swap behavior. + */ + struct SingleSwap { + bytes32 poolId; + SwapKind kind; + address assetIn; + address assetOut; + uint256 amount; + bytes userData; + } + + /** + * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the + * `recipient` account. + * + * If the caller is not `sender`, it must be an authorized relayer for them. + * + * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20 + * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender` + * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of + * `joinPool`. + * + * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of + * transferred. This matches the behavior of `exitPool`. + * + * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a + * revert. + */ + struct FundManagement { + address sender; + bool fromInternalBalance; + address payable recipient; + bool toInternalBalance; + } + + /** + * @dev Performs a swap with a single Pool. + * + * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens + * taken from the Pool, which must be greater than or equal to `limit`. + * + * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens + * sent to the Pool, which must be less than or equal to `limit`. + * + * Internal Balance usage and the recipient are determined by the `funds` struct. + * + * Emits a `Swap` event. + */ + function swap( + SingleSwap memory singleSwap, + FundManagement memory funds, + uint256 limit, + uint256 deadline + ) external payable returns (uint256); +} diff --git a/contracts/interfaces/IEthBlocklistErc20Vault.sol b/contracts/interfaces/IEthBlocklistErc20Vault.sol new file mode 100644 index 00000000..3f41f0f3 --- /dev/null +++ b/contracts/interfaces/IEthBlocklistErc20Vault.sol @@ -0,0 +1,13 @@ +// 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 {} diff --git a/contracts/interfaces/IEthBlocklistVault.sol b/contracts/interfaces/IEthBlocklistVault.sol new file mode 100644 index 00000000..35683da3 --- /dev/null +++ b/contracts/interfaces/IEthBlocklistVault.sol @@ -0,0 +1,13 @@ +// 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 {} 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 c8226887..f73b8d39 100644 --- a/contracts/interfaces/IEthFoxVault.sol +++ b/contracts/interfaces/IEthFoxVault.sol @@ -31,6 +31,13 @@ interface IEthFoxVault is IVaultBlocklist, IMulticall { + /** + * @notice Event emitted when a user is ejected from the Vault + * @param user The address of the user + * @param shares The amount of shares ejected + */ + event UserEjected(address user, uint256 shares); + /** * @dev Struct for initializing the EthFoxVault contract * @param admin The address of the Vault admin @@ -64,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/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/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/IGnoBlocklistErc20Vault.sol b/contracts/interfaces/IGnoBlocklistErc20Vault.sol new file mode 100644 index 00000000..2959ef84 --- /dev/null +++ b/contracts/interfaces/IGnoBlocklistErc20Vault.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultBlocklist} from './IVaultBlocklist.sol'; +import {IGnoErc20Vault} from './IGnoErc20Vault.sol'; + +/** + * @title IGnoBlocklistErc20Vault + * @author StakeWise + * @notice Defines the interface for the GnoBlocklistErc20Vault contract + */ +interface IGnoBlocklistErc20Vault is IGnoErc20Vault, IVaultBlocklist {} diff --git a/contracts/interfaces/IGnoBlocklistVault.sol b/contracts/interfaces/IGnoBlocklistVault.sol new file mode 100644 index 00000000..6e66d37e --- /dev/null +++ b/contracts/interfaces/IGnoBlocklistVault.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultBlocklist} from './IVaultBlocklist.sol'; +import {IGnoVault} from './IGnoVault.sol'; + +/** + * @title IGnoBlocklistVault + * @author StakeWise + * @notice Defines the interface for the GnoBlocklistVault contract + */ +interface IGnoBlocklistVault is IGnoVault, IVaultBlocklist {} diff --git a/contracts/interfaces/IGnoErc20Vault.sol b/contracts/interfaces/IGnoErc20Vault.sol new file mode 100644 index 00000000..ad09a826 --- /dev/null +++ b/contracts/interfaces/IGnoErc20Vault.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultAdmin} from './IVaultAdmin.sol'; +import {IVaultVersion} from './IVaultVersion.sol'; +import {IVaultFee} from './IVaultFee.sol'; +import {IVaultState} from './IVaultState.sol'; +import {IVaultValidators} from './IVaultValidators.sol'; +import {IVaultEnterExit} from './IVaultEnterExit.sol'; +import {IVaultOsToken} from './IVaultOsToken.sol'; +import {IVaultMev} from './IVaultMev.sol'; +import {IVaultGnoStaking} from './IVaultGnoStaking.sol'; +import {IMulticall} from './IMulticall.sol'; +import {IVaultToken} from './IVaultToken.sol'; + +/** + * @title IGnoErc20Vault + * @author StakeWise + * @notice Defines the interface for the GnoErc20Vault contract + */ +interface IGnoErc20Vault is + IVaultAdmin, + IVaultVersion, + IVaultFee, + IVaultState, + IVaultValidators, + IVaultEnterExit, + IVaultOsToken, + IVaultMev, + IVaultToken, + IVaultGnoStaking, + IMulticall +{ + /** + * @dev Struct for initializing the GnoErc20Vault contract + * @param capacity The Vault stops accepting deposits after exceeding the capacity + * @param feePercent The fee percent that is charged by the Vault + * @param name The name of the ERC20 token + * @param symbol The symbol of the ERC20 token + * @param metadataIpfsHash The IPFS hash of the Vault's metadata file + */ + struct GnoErc20VaultInitParams { + uint256 capacity; + uint16 feePercent; + string name; + string symbol; + string metadataIpfsHash; + } + + /** + * @notice Initializes or upgrades the GnoErc20Vault contract. Must transfer security deposit during the deployment. + * @param params The encoded parameters for initializing the GnoErc20Vault contract + */ + function initialize(bytes calldata params) external; +} diff --git a/contracts/interfaces/IGnoGenesisVault.sol b/contracts/interfaces/IGnoGenesisVault.sol new file mode 100644 index 00000000..c05c7375 --- /dev/null +++ b/contracts/interfaces/IGnoGenesisVault.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IGnoVault} from './IGnoVault.sol'; + +/** + * @title IGnoGenesisVault + * @author StakeWise + * @notice Defines the interface for the GnoGenesisVault contract + */ +interface IGnoGenesisVault is IGnoVault { + /** + * @notice Event emitted on migration from StakeWise v2 + * @param receiver The address of the shares receiver + * @param assets The amount of assets migrated + * @param shares The amount of shares migrated + */ + event Migrated(address receiver, uint256 assets, uint256 shares); + + /** + * @notice Event emitted on GnoGenesisVault creation + * @param admin The address of the Vault admin + * @param capacity The capacity of the Vault + * @param feePercent The fee percent of the Vault + * @param metadataIpfsHash The IPFS hash of the Vault metadata + */ + event GenesisVaultCreated( + address admin, + uint256 capacity, + uint16 feePercent, + string metadataIpfsHash + ); + + /** + * @notice Function for migrating from StakeWise v2. Can be called only by RewardGnoToken contract. + * @param receiver The address of the receiver + * @param assets The amount of assets migrated + * @return shares The amount of shares minted + */ + function migrate(address receiver, uint256 assets) external returns (uint256 shares); + + /** + * @notice Function for accepting PoolEscrow contract ownership. Can only be called once by the admin. + */ + function acceptPoolEscrowOwnership() external; +} diff --git a/contracts/interfaces/IGnoPoolEscrow.sol b/contracts/interfaces/IGnoPoolEscrow.sol new file mode 100644 index 00000000..88b8954c --- /dev/null +++ b/contracts/interfaces/IGnoPoolEscrow.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +pragma solidity 0.8.22; + +/** + * @title IPoolEscrow + * @author StakeWise + * @dev Copied from https://github.com/stakewise/contracts/blob/gnosis-chain/contracts/interfaces/IPoolEscrow.sol + * @notice Defines the interface for the PoolEscrow contract + */ +interface IGnoPoolEscrow { + /** + * @dev Event for tracking withdrawals. + * @param sender - the address of the transaction sender. + * @param payee - the address where the funds were transferred to. + * @param amount - the amount transferred to payee. + */ + event Withdrawn(address indexed sender, address indexed payee, uint256 amount); + + /** + * @dev Event for tracking ownership transfer commits. + * @param currentOwner - the address of the current owner. + * @param futureOwner - the address the ownership is planned to be transferred to. + */ + event OwnershipTransferCommitted(address indexed currentOwner, address indexed futureOwner); + + /** + * @dev Event for tracking ownership transfers. + * @param previousOwner - the address the ownership was transferred from. + * @param newOwner - the address the ownership was transferred to. + */ + event OwnershipTransferApplied(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Function for retrieving the address of the current owner. + */ + function owner() external view returns (address); + + /** + * @dev Function for retrieving the address of the future owner. + */ + function futureOwner() external view returns (address); + + /** + * @dev Commit contract ownership transfer to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function commitOwnershipTransfer(address newOwner) external; + + /** + * @dev Apply contract ownership transfer to a new account (`futureOwner`). + * Can only be called by the future owner. + */ + function applyOwnershipTransfer() external; + + /** + * @dev Withdraw tokens from the escrow. Can only be called by the current owner. + * @param token - the address of the token to transfer. + * @param payee - the address where the funds will be transferred to. + * @param amount - the amount of tokens to transfer to payee. + */ + function withdrawTokens(address token, address payee, uint256 amount) external; + + /** + * @dev Withdraw balance for a payee, forwarding all gas to the + * recipient. Can only be called by the current owner. + * + * WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities. + * Make sure you trust the recipient, or are either following the + * checks-effects-interactions pattern or using {ReentrancyGuard}. + * + * @param payee - the address where the funds will be transferred to. + * @param amount - the amount of xDAI to transfer to payee. + */ + function withdraw(address payable payee, uint256 amount) external; +} diff --git a/contracts/interfaces/IGnoPrivErc20Vault.sol b/contracts/interfaces/IGnoPrivErc20Vault.sol new file mode 100644 index 00000000..3e734c1d --- /dev/null +++ b/contracts/interfaces/IGnoPrivErc20Vault.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultWhitelist} from './IVaultWhitelist.sol'; +import {IGnoErc20Vault} from './IGnoErc20Vault.sol'; + +/** + * @title IGnoPrivErc20Vault + * @author StakeWise + * @notice Defines the interface for the GnoPrivErc20Vault contract + */ +interface IGnoPrivErc20Vault is IGnoErc20Vault, IVaultWhitelist {} diff --git a/contracts/interfaces/IGnoPrivVault.sol b/contracts/interfaces/IGnoPrivVault.sol new file mode 100644 index 00000000..33d4cbf0 --- /dev/null +++ b/contracts/interfaces/IGnoPrivVault.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultWhitelist} from './IVaultWhitelist.sol'; +import {IGnoVault} from './IGnoVault.sol'; + +/** + * @title IGnoPrivVault + * @author StakeWise + * @notice Defines the interface for the GnoPrivVault contract + */ +interface IGnoPrivVault is IGnoVault, IVaultWhitelist {} diff --git a/contracts/interfaces/IGnoValidatorsRegistry.sol b/contracts/interfaces/IGnoValidatorsRegistry.sol new file mode 100644 index 00000000..a70aa8ce --- /dev/null +++ b/contracts/interfaces/IGnoValidatorsRegistry.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: CC0-1.0 + +pragma solidity =0.8.22; + +import {IValidatorsRegistry} from './IValidatorsRegistry.sol'; + +/** + * @title IGnoValidatorsRegistry + * @author Gnosis + * @notice This is the Gnosis validators deposit contract interface. + * See https://github.com/gnosischain/deposit-contract/blob/master/contracts/SBCDepositContract.sol. + */ +interface IGnoValidatorsRegistry is IValidatorsRegistry { + /// @notice The amount of GNO that is withdrawable by the address + function withdrawableAmount(address _address) external view returns (uint256); + + /// @notice Submit a Phase 0 DepositData object. + /// @param pubkey A BLS12-381 public key. + /// @param withdrawal_credentials Commitment to a public key for withdrawals. + /// @param signature A BLS12-381 signature. + /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object. + /// @param stake_amount The amount of GNO to stake. + /// Used as a protection against malformed input. + function deposit( + bytes memory pubkey, + bytes memory withdrawal_credentials, + bytes memory signature, + bytes32 deposit_data_root, + uint256 stake_amount + ) external; + + /// @notice Submit multiple Phase 0 DepositData objects. + /// @param pubkeys Concatenated array of BLS12-381 public keys. + /// @param withdrawal_credentials Commitment to a public key for withdrawals. + /// @param signatures Concatenated array of BLS12-381 signatures. + /// @param deposit_data_roots Array of SHA-256 hashes of the SSZ-encoded DepositData objects. + function batchDeposit( + bytes calldata pubkeys, + bytes calldata withdrawal_credentials, + bytes calldata signatures, + bytes32[] calldata deposit_data_roots + ) external; + + /// @notice Claim withdrawal amount for an address. + /// @param _address Address to transfer withdrawable tokens. + function claimWithdrawal(address _address) external; +} diff --git a/contracts/interfaces/IGnoVault.sol b/contracts/interfaces/IGnoVault.sol new file mode 100644 index 00000000..ac1870a2 --- /dev/null +++ b/contracts/interfaces/IGnoVault.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultAdmin} from './IVaultAdmin.sol'; +import {IVaultVersion} from './IVaultVersion.sol'; +import {IVaultFee} from './IVaultFee.sol'; +import {IVaultState} from './IVaultState.sol'; +import {IVaultValidators} from './IVaultValidators.sol'; +import {IVaultEnterExit} from './IVaultEnterExit.sol'; +import {IVaultOsToken} from './IVaultOsToken.sol'; +import {IVaultMev} from './IVaultMev.sol'; +import {IVaultGnoStaking} from './IVaultGnoStaking.sol'; +import {IMulticall} from './IMulticall.sol'; + +/** + * @title IGnoVault + * @author StakeWise + * @notice Defines the interface for the GnoVault contract + */ +interface IGnoVault is + IVaultAdmin, + IVaultVersion, + IVaultFee, + IVaultState, + IVaultValidators, + IVaultEnterExit, + IVaultOsToken, + IVaultMev, + IVaultGnoStaking, + IMulticall +{ + /** + * @dev Struct for initializing the GnoVault contract + * @param capacity The Vault stops accepting deposits after exceeding the capacity + * @param feePercent The fee percent that is charged by the Vault + * @param metadataIpfsHash The IPFS hash of the Vault's metadata file + */ + struct GnoVaultInitParams { + uint256 capacity; + uint16 feePercent; + string metadataIpfsHash; + } + + /** + * @notice Initializes or upgrades the GnoVault contract. Must transfer security deposit during the deployment. + * @param params The encoded parameters for initializing the GnoVault contract + */ + function initialize(bytes calldata params) external; +} diff --git a/contracts/interfaces/IGnoVaultFactory.sol b/contracts/interfaces/IGnoVaultFactory.sol new file mode 100644 index 00000000..4681d1c6 --- /dev/null +++ b/contracts/interfaces/IGnoVaultFactory.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +/** + * @title IGnoVaultFactory + * @author StakeWise + * @notice Defines the interface for the GNO Vault Factory contract + */ +interface IGnoVaultFactory { + /** + * @notice Event emitted on a Vault creation + * @param admin The address of the Vault admin + * @param vault The address of the created Vault + * @param ownMevEscrow The address of the own MEV escrow contract. Zero address if shared MEV escrow is used. + * @param params The encoded parameters for initializing the Vault contract + */ + event VaultCreated( + address indexed admin, + address indexed vault, + address ownMevEscrow, + bytes params + ); + + /** + * @notice The address of the Vault implementation contract used for proxy creation + * @return The address of the Vault implementation contract + */ + function implementation() external view returns (address); + + /** + * @notice The address of the own MEV escrow contract used for Vault creation + * @return The address of the MEV escrow contract + */ + function ownMevEscrow() external view returns (address); + + /** + * @notice The address of the Vault admin used for Vault creation + * @return The address of the Vault admin + */ + function vaultAdmin() external view returns (address); + + /** + * @notice Create Vault. Must transfer security deposit together with a call. + * @param params The encoded parameters for initializing the Vault contract + * @param isOwnMevEscrow Whether to deploy own escrow contract or connect to a smoothing pool for priority fees and MEV rewards + * @return vault The address of the created Vault + */ + function createVault(bytes calldata params, bool isOwnMevEscrow) external returns (address vault); +} diff --git a/contracts/interfaces/IRewardGnoToken.sol b/contracts/interfaces/IRewardGnoToken.sol new file mode 100644 index 00000000..1f86f707 --- /dev/null +++ b/contracts/interfaces/IRewardGnoToken.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +pragma solidity 0.8.22; + +/** + * @title IRewardGnoToken + * @author StakeWise + * @dev Copied from https://github.com/stakewise/contracts/blob/gnosis-chain/contracts/interfaces/IRewardToken.sol + * @notice Defines the interface for the IRewardGnoToken contract + */ +interface IRewardGnoToken { + /** + * @dev Function for getting the total assets. + */ + function totalAssets() external view returns (uint256); + + /** + * @dev Function for retrieving the total rewards amount. + */ + function totalRewards() external view returns (uint128); + + /** + * @dev Function for getting the total penalty. + */ + function totalPenalty() external view returns (uint256); + + /** + * @dev Function for updating validators total rewards. + * Can only be called by Vault contract. + * @param rewardsDelta - the total rewards earned or penalties received. + */ + function updateTotalRewards(int256 rewardsDelta) external; +} 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..8eff2cba 100644 --- a/contracts/interfaces/IVaultEnterExit.sol +++ b/contracts/interfaces/IVaultEnterExit.sol @@ -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 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 @@ -49,11 +49,26 @@ interface IVaultEnterExit is IVaultState { 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 + ); + /** * @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( @@ -64,8 +79,8 @@ interface IVaultEnterExit is IVaultState { ); /** - * @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 +98,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 +118,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/IVaultGnoStaking.sol b/contracts/interfaces/IVaultGnoStaking.sol new file mode 100644 index 00000000..e341ff6a --- /dev/null +++ b/contracts/interfaces/IVaultGnoStaking.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IVaultValidators} from './IVaultValidators.sol'; +import {IVaultEnterExit} from './IVaultEnterExit.sol'; + +/** + * @title IVaultGnoStaking + * @author StakeWise + * @notice Defines the interface for the VaultGnoStaking contract + */ +interface IVaultGnoStaking is IVaultValidators, IVaultEnterExit { + /** + * @notice Emitted when xDAI is swapped to GNO + * @param amount The amount of xDAI swapped + * @param assets The amount of GNO received + */ + event XdaiSwapped(uint256 amount, uint256 assets); + + /** + * @notice Emitted when the xDAI manager is updated + * @param caller The address of the caller + * @param xdaiManager The address of the new xDAI manager + */ + event XdaiManagerUpdated(address caller, address xdaiManager); + + /** + * @notice The Vault xDAI manager address. Defaults to the admin address. + * @return The address that can swap xDAI to GNO + */ + function xdaiManager() external view returns (address); + + /** + * @notice Deposit GNO to the Vault + * @param assets The amount of GNO to deposit + * @param receiver The address that will receive Vault's shares + * @param referrer The address of the referrer. Set to zero address if not used. + * @return shares The number of shares minted + */ + function deposit( + uint256 assets, + address receiver, + address referrer + ) external returns (uint256 shares); + + /** + * @notice Swap xDAI to GNO. Can only be called by the xDAI manager. + * @param amount The amount of xDAI to swap + * @param limit The minimum amount of GNO to receive + * @param deadline The deadline for the swap + */ + function swapXdaiToGno( + uint256 amount, + uint256 limit, + uint256 deadline + ) external returns (uint256 assets); + + /** + * @notice Set the address of the xDAI manager. Only admin can call this function. + * @param xdaiManager_ The address of the new xDAI manager + */ + function setXdaiManager(address xdaiManager_) external; +} diff --git a/contracts/interfaces/IVaultState.sol b/contracts/interfaces/IVaultState.sol index 1223f87a..e82b1681 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 */ @@ -56,6 +56,12 @@ interface IVaultState is IVaultFee { */ function queuedShares() external view returns (uint128); + /** + * @notice Total Exiting Assets + * @return The total number of assets queued for exit + */ + function totalExitingAssets() external view returns (uint128); + /** * @notice Returns the number of shares held by an account * @param account The account for which to look up the number of shares it has, i.e. its balance diff --git a/contracts/interfaces/IXdaiExchange.sol b/contracts/interfaces/IXdaiExchange.sol new file mode 100644 index 00000000..7f46fa22 --- /dev/null +++ b/contracts/interfaces/IXdaiExchange.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +/** + * @title IXdaiExchange + * @author StakeWise + * @notice Defines the interface for the xDAI exchange contract + */ +interface IXdaiExchange { + /** + * @notice Initializes the xDAI exchange contract. Can only be called once. + * @param initialOwner The address of the initial owner + */ + function initialize(address initialOwner) external; + + /** + * @notice Swaps xDAI to GNO. The amount of xDAI to swap is determined by the value of msg.value. + * Can only be called by the xDAI manager. + * @param limit The minimum amount of GNO to receive + * @param deadline The deadline for the swap + * @return assets The amount of GNO received + */ + function swap(uint256 limit, uint256 deadline) external payable returns (uint256 assets); +} 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/misc/XdaiExchange.sol b/contracts/misc/XdaiExchange.sol new file mode 100644 index 00000000..c5482d5b --- /dev/null +++ b/contracts/misc/XdaiExchange.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {UUPSUpgradeable} from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol'; +import {Ownable2StepUpgradeable} from '@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol'; +import {IXdaiExchange} from '../interfaces/IXdaiExchange.sol'; +import {IBalancerVault} from '../interfaces/IBalancerVault.sol'; +import {IVaultsRegistry} from '../interfaces/IVaultsRegistry.sol'; +import {Errors} from '../libraries/Errors.sol'; + +/** + * @title XdaiExchange + * @author StakeWise + * @notice Defines the xDAI to GNO exchange functionality + */ +contract XdaiExchange is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable, IXdaiExchange { + address private immutable _gnoToken; + bytes32 private immutable _balancerPoolId; + IBalancerVault private immutable _balancerVault; + IVaultsRegistry private immutable _vaultsRegistry; + + /** + * @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 gnoToken The address of the GNO token + * @param balancerPoolId The Balancer pool ID for the xDAI to GNO exchange + * @param balancerVault The address of the Balancer Vault + * @param vaultsRegistry The address of the Vaults Registry + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address gnoToken, + bytes32 balancerPoolId, + address balancerVault, + address vaultsRegistry + ) { + _gnoToken = gnoToken; + _balancerPoolId = balancerPoolId; + _balancerVault = IBalancerVault(balancerVault); + _vaultsRegistry = IVaultsRegistry(vaultsRegistry); + _disableInitializers(); + } + + /// @inheritdoc IXdaiExchange + function initialize(address initialOwner) external override initializer { + __Ownable_init(initialOwner); + } + + /// @inheritdoc IXdaiExchange + function swap(uint256 limit, uint256 deadline) external payable virtual returns (uint256 assets) { + if (msg.value == 0) revert Errors.InvalidAssets(); + if (!_vaultsRegistry.vaults(msg.sender)) revert Errors.AccessDenied(); + + // define balancer swap + IBalancerVault.SingleSwap memory singleSwap = IBalancerVault.SingleSwap({ + poolId: _balancerPoolId, + kind: IBalancerVault.SwapKind.GIVEN_IN, + assetIn: address(0), + assetOut: _gnoToken, + amount: msg.value, + userData: '' + }); + + // define balancer funds + IBalancerVault.FundManagement memory funds = IBalancerVault.FundManagement({ + sender: address(this), + fromInternalBalance: false, + recipient: payable(msg.sender), + toInternalBalance: false + }); + + // swap xDAI to GNO + assets = _balancerVault.swap{value: msg.value}(singleSwap, funds, limit, deadline); + } + + /// @inheritdoc UUPSUpgradeable + function _authorizeUpgrade(address) internal override onlyOwner {} +} diff --git a/contracts/mocks/BalancerVaultMock.sol b/contracts/mocks/BalancerVaultMock.sol new file mode 100644 index 00000000..9e9a6e33 --- /dev/null +++ b/contracts/mocks/BalancerVaultMock.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import {Address} from '@openzeppelin/contracts/utils/Address.sol'; +import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; +import {IBalancerVault} from '../interfaces/IBalancerVault.sol'; + +/** + * @title BalancerVaultMock + * @author StakeWise + * @notice Defines the mock for the Balancer Vault contract + */ +contract BalancerVaultMock is Ownable, IBalancerVault { + using SafeERC20 for IERC20; + + error SwapExpired(); + error InvalidSingleSwap(); + error InvalidFundManagement(); + error LimitExceeded(); + + uint256 private constant _wad = 1e18; + + address private immutable _outputToken; + uint256 public xdaiGnoRate; + + constructor( + address outputToken, + uint256 _xdaiGnoRate, + address _initialOwner + ) Ownable(_initialOwner) { + _outputToken = outputToken; + xdaiGnoRate = _xdaiGnoRate; + } + + function swap( + SingleSwap calldata singleSwap, + FundManagement calldata funds, + uint256 limit, + uint256 deadline + ) external payable returns (uint256 amountOut) { + if (deadline < block.timestamp) { + revert SwapExpired(); + } + + if ( + singleSwap.kind != SwapKind.GIVEN_IN || + singleSwap.assetIn != address(0) || + singleSwap.assetOut != _outputToken + ) { + revert InvalidSingleSwap(); + } + + if (funds.sender != msg.sender || funds.fromInternalBalance || funds.toInternalBalance) { + revert InvalidFundManagement(); + } + + amountOut = (msg.value * xdaiGnoRate) / _wad; + if (amountOut < limit) { + revert LimitExceeded(); + } + IERC20(_outputToken).safeTransfer(funds.recipient, amountOut); + } + + function setXdaiGnoRate(uint256 newRate) external onlyOwner { + xdaiGnoRate = newRate; + } + + function drain() external onlyOwner { + Address.sendValue(payable(msg.sender), address(this).balance); + IERC20(_outputToken).safeTransfer(msg.sender, IERC20(_outputToken).balanceOf(address(this))); + } +} 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/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/mocks/PoolEscrowMock.sol b/contracts/mocks/PoolEscrowMock.sol index b9c0b3d4..b1500137 100644 --- a/contracts/mocks/PoolEscrowMock.sol +++ b/contracts/mocks/PoolEscrowMock.sol @@ -2,8 +2,10 @@ pragma solidity 0.8.22; -import '@openzeppelin/contracts/utils/Address.sol'; -import '../interfaces/IPoolEscrow.sol'; +import {Address} from '@openzeppelin/contracts/utils/Address.sol'; +import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {IGnoPoolEscrow} from '../interfaces/IGnoPoolEscrow.sol'; /** * @title PoolEscrowMock @@ -13,8 +15,9 @@ 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 IGnoPoolEscrow { using Address for address payable; + using SafeERC20 for IERC20; // @dev The address of the current contract owner. address public override owner; @@ -68,6 +71,20 @@ contract PoolEscrowMock is IPoolEscrow { payee.sendValue(amount); } + /** + * @dev See {IPoolEscrow-withdraw}. + */ + function withdrawTokens( + address token, + address payee, + uint256 amount + ) external override onlyOwner { + require(payee != address(0), 'PoolEscrow: payee is the zero address'); + require(token != address(0), 'PoolEscrow: token is the zero address'); + emit Withdrawn(msg.sender, payee, amount); + IERC20(token).safeTransfer(payee, amount); + } + /** * @dev Function for receiving withdrawals from ETH2 system contract. */ diff --git a/contracts/mocks/PriceFeedMock.sol b/contracts/mocks/PriceFeedMock.sol new file mode 100644 index 00000000..8ccadc98 --- /dev/null +++ b/contracts/mocks/PriceFeedMock.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; +import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol'; +import {IChainlinkV3Aggregator} from '../interfaces/IChainlinkV3Aggregator.sol'; +import {IBalancerRateProvider} from '../interfaces/IBalancerRateProvider.sol'; + +/** + * @title PriceFeed + * @author StakeWise + * @notice Price feed mock + */ +contract PriceFeedMock is + Ownable, + IBalancerRateProvider, + IChainlinkAggregator, + IChainlinkV3Aggregator +{ + /// @inheritdoc IChainlinkV3Aggregator + uint256 public constant override version = 0; + + /// @inheritdoc IChainlinkV3Aggregator + string public override description; + + uint256 private _rate; + + /** + * @dev Constructor + * @param _description The description of the price feed + */ + constructor(string memory _description) Ownable(msg.sender) { + description = _description; + } + + /// @inheritdoc IBalancerRateProvider + function getRate() public view override returns (uint256) { + return _rate; + } + + function setRate(uint256 rate) external onlyOwner { + _rate = rate; + } + + /// @inheritdoc IChainlinkAggregator + function latestAnswer() public view override returns (int256) { + uint256 value = getRate(); + // cannot realistically overflow, but better to check + return (value > uint256(type(int256).max)) ? type(int256).max : int256(value); + } + + /// @inheritdoc IChainlinkAggregator + function latestTimestamp() external view returns (uint256) { + return block.timestamp; + } + + /// @inheritdoc IChainlinkV3Aggregator + function decimals() public pure returns (uint8) { + return 18; + } + + /// @inheritdoc IChainlinkV3Aggregator + function latestRoundData() + external + view + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) + { + return (0, latestAnswer(), block.timestamp, block.timestamp, 0); + } +} diff --git a/contracts/mocks/XdaiExchangeV2Mock.sol b/contracts/mocks/XdaiExchangeV2Mock.sol new file mode 100644 index 00000000..83c771c2 --- /dev/null +++ b/contracts/mocks/XdaiExchangeV2Mock.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {XdaiExchange} from '../misc/XdaiExchange.sol'; + +contract XdaiExchangeV2Mock is XdaiExchange { + uint256 public newVar; + + constructor( + address gnoToken, + bytes32 balancerPoolId, + address balancerVault, + address vaultsRegistry + ) XdaiExchange(gnoToken, balancerPoolId, balancerVault, vaultsRegistry) {} + + function initializeV2(address initialOwner) external reinitializer(2) {} + + // invalid swap function + function swap(uint256 limit, uint256) external payable override returns (uint256 assets) { + return limit; + } +} diff --git a/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol new file mode 100644 index 00000000..9d505f76 --- /dev/null +++ b/contracts/vaults/ethereum/EthBlocklistErc20Vault.sol @@ -0,0 +1,129 @@ +// 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 +{ + // slither-disable-next-line shadowing-state + 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 delay after which the assets can be claimed after exiting from staking + */ + /// @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 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..a1c84758 --- /dev/null +++ b/contracts/vaults/ethereum/EthBlocklistVault.sol @@ -0,0 +1,116 @@ +// 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 { + // slither-disable-next-line shadowing-state + 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 delay after which the assets can be claimed after exiting from staking + */ + /// @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 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..52a1a02f 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, @@ -54,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( @@ -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,7 +131,7 @@ contract EthErc20Vault is /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { - return 1; + return _version; } /// @inheritdoc VaultState @@ -188,6 +181,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..4ea47010 100644 --- a/contracts/vaults/ethereum/EthGenesisVault.sol +++ b/contracts/vaults/ethereum/EthGenesisVault.sol @@ -5,10 +5,8 @@ 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 {IEthPoolEscrow} from '../../interfaces/IEthPoolEscrow.sol'; import {IEthGenesisVault} from '../../interfaces/IEthGenesisVault.sol'; import {IRewardEthToken} from '../../interfaces/IRewardEthToken.sol'; import {IKeeperRewards} from '../../interfaces/IKeeperRewards.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,8 +23,11 @@ import {EthVault} 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 - IPoolEscrow private immutable _poolEscrow; + IEthPoolEscrow private immutable _poolEscrow; /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IRewardEthToken private immutable _rewardEthToken; @@ -45,7 +46,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( @@ -69,22 +70,28 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { exitingAssetsClaimDelay ) { - _poolEscrow = IPoolEscrow(poolEscrow); + _poolEscrow = IEthPoolEscrow(poolEscrow); _rewardEthToken = IRewardEthToken(rewardEthToken); } /// @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 +111,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 @@ -125,31 +132,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(); @@ -185,12 +169,49 @@ 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, uint256 assets ) internal virtual override(VaultEnterExit, VaultEthStaking) { - if (assets > super._vaultAssets()) _pullAssets(); + if (assets > super._vaultAssets()) _pullWithdrawals(); return super._transferVaultAssets(receiver, assets); } @@ -212,7 +233,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault { function _registerSingleValidator( bytes calldata validator ) internal virtual override(VaultValidators, VaultEthStaking) { - _pullAssets(); + _pullWithdrawals(); super._registerSingleValidator(validator); } @@ -221,14 +242,14 @@ 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); } diff --git a/contracts/vaults/ethereum/EthPrivErc20Vault.sol b/contracts/vaults/ethereum/EthPrivErc20Vault.sol index abe179c1..2577c287 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,9 @@ import {EthErc20Vault} 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; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -30,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 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( @@ -56,15 +57,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); + __VaultWhitelist_init(_admin); } /// @inheritdoc IVaultVersion @@ -74,7 +81,7 @@ contract EthPrivErc20Vault is Initializable, EthErc20Vault, VaultWhitelist, IEth /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, EthErc20Vault) returns (uint8) { - return 1; + return _version; } /// @inheritdoc IVaultEthStaking @@ -82,9 +89,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 +98,27 @@ 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 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..1652a4fd 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 {IVaultVersion} from '../modules/VaultVersion.sol'; +import {EthVault, IEthVault} from './EthVault.sol'; /** * @title EthPrivVault @@ -20,6 +17,9 @@ import {EthVault} 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; + /** * @dev Constructor * @dev Since the immutable variable value is stored in the bytecode, @@ -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 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( @@ -56,15 +56,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 +78,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 +87,20 @@ 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 IVaultVersion function vaultId() public pure virtual override(IVaultVersion, EthVault) returns (bytes32) { return keccak256('EthPrivVault'); @@ -93,7 +108,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..68689eca 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, @@ -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) { @@ -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 e27d0dc0..6023e038 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, @@ -44,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( @@ -52,17 +54,25 @@ contract EthFoxVault is address _vaultsRegistry, address _validatorsRegistry, address sharedMevEscrow, - uint256 exitedAssetsClaimDelay + uint256 exitingAssetsClaimDelay ) VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) - VaultEnterExit(exitedAssetsClaimDelay) + VaultEnterExit(exitingAssetsClaimDelay) VaultMev(sharedMevEscrow) { _disableInitializers(); } /// @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,13 +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); - } + // send user shares to exit queue + _enterExitQueue(user, userShares, user); + emit UserEjected(user, userShares); } /** @@ -117,7 +123,7 @@ contract EthFoxVault is /// @inheritdoc IVaultVersion function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { - return 1; + return _version; } /** @@ -136,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/gnosis/GnoBlocklistErc20Vault.sol b/contracts/vaults/gnosis/GnoBlocklistErc20Vault.sol new file mode 100644 index 00000000..2814bdff --- /dev/null +++ b/contracts/vaults/gnosis/GnoBlocklistErc20Vault.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoBlocklistErc20Vault} from '../../interfaces/IGnoBlocklistErc20Vault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {ERC20Upgradeable} from '../../base/ERC20Upgradeable.sol'; +import {VaultGnoStaking, IVaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {VaultBlocklist} from '../modules/VaultBlocklist.sol'; +import {GnoErc20Vault, IGnoErc20Vault} from './GnoErc20Vault.sol'; + +/** + * @title GnoBlocklistErc20Vault + * @author StakeWise + * @notice Defines the Gnosis staking Vault with blocking and ERC-20 functionality + */ +contract GnoBlocklistErc20Vault is + Initializable, + GnoErc20Vault, + VaultBlocklist, + IGnoBlocklistErc20Vault +{ + // slither-disable-next-line shadowing-state + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + GnoErc20Vault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IGnoErc20Vault + function initialize( + bytes calldata params + ) external virtual override(IGnoErc20Vault, GnoErc20Vault) reinitializer(_version) { + // initialize deployed vault + address _admin = IGnoVaultFactory(msg.sender).vaultAdmin(); + __GnoErc20Vault_init( + _admin, + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoErc20VaultInitParams)) + ); + // blocklist manager is initially set to admin address + __VaultBlocklist_init(_admin); + } + + /// @inheritdoc IVaultGnoStaking + function deposit( + uint256 assets, + address receiver, + address referrer + ) public virtual override(IVaultGnoStaking, VaultGnoStaking) returns (uint256 shares) { + _checkBlocklist(msg.sender); + _checkBlocklist(receiver); + return super.deposit(assets, receiver, referrer); + } + + /// @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 IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, GnoErc20Vault) returns (bytes32) { + return keccak256('GnoBlocklistErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, GnoErc20Vault) 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/gnosis/GnoBlocklistVault.sol b/contracts/vaults/gnosis/GnoBlocklistVault.sol new file mode 100644 index 00000000..28c03138 --- /dev/null +++ b/contracts/vaults/gnosis/GnoBlocklistVault.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoBlocklistVault} from '../../interfaces/IGnoBlocklistVault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultGnoStaking, IVaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultBlocklist} from '../modules/VaultBlocklist.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {GnoVault, IGnoVault} from './GnoVault.sol'; + +/** + * @title GnoBlocklistVault + * @author StakeWise + * @notice Defines the Gnosis staking Vault with blocking addresses functionality + */ +contract GnoBlocklistVault is Initializable, GnoVault, VaultBlocklist, IGnoBlocklistVault { + // slither-disable-next-line shadowing-state + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + GnoVault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IGnoVault + function initialize( + bytes calldata params + ) external virtual override(IGnoVault, GnoVault) reinitializer(_version) { + // initialize deployed vault + address _admin = IGnoVaultFactory(msg.sender).vaultAdmin(); + __GnoVault_init( + _admin, + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoVaultInitParams)) + ); + // blocklist manager is initially set to admin address + __VaultBlocklist_init(_admin); + } + + /// @inheritdoc IVaultGnoStaking + function deposit( + uint256 assets, + address receiver, + address referrer + ) public virtual override(IVaultGnoStaking, VaultGnoStaking) returns (uint256 shares) { + _checkBlocklist(msg.sender); + _checkBlocklist(receiver); + return super.deposit(assets, receiver, referrer); + } + + /// @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 IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, GnoVault) returns (bytes32) { + return keccak256('GnoBlocklistVault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, GnoVault) 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/gnosis/GnoErc20Vault.sol b/contracts/vaults/gnosis/GnoErc20Vault.sol new file mode 100644 index 00000000..cf5010f1 --- /dev/null +++ b/contracts/vaults/gnosis/GnoErc20Vault.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoErc20Vault} from '../../interfaces/IGnoErc20Vault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {Multicall} from '../../base/Multicall.sol'; +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, IVaultVersion} from '../modules/VaultVersion.sol'; +import {VaultImmutables} from '../modules/VaultImmutables.sol'; +import {VaultState} from '../modules/VaultState.sol'; +import {VaultEnterExit, IVaultEnterExit} from '../modules/VaultEnterExit.sol'; +import {VaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultMev} from '../modules/VaultMev.sol'; +import {VaultToken} from '../modules/VaultToken.sol'; + +/** + * @title GnoErc20Vault + * @author StakeWise + * @notice Defines the Gnosis staking Vault with ERC-20 token + */ +contract GnoErc20Vault is + VaultImmutables, + Initializable, + VaultAdmin, + VaultVersion, + VaultFee, + VaultState, + VaultValidators, + VaultEnterExit, + VaultOsToken, + VaultMev, + VaultToken, + VaultGnoStaking, + Multicall, + IGnoErc20Vault +{ + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) + VaultEnterExit(exitingAssetsClaimDelay) + VaultOsToken(osTokenVaultController, osTokenConfig) + VaultMev(sharedMevEscrow) + VaultGnoStaking(gnoToken, xdaiExchange) + { + _disableInitializers(); + } + + /// @inheritdoc IGnoErc20Vault + function initialize(bytes calldata params) external virtual override reinitializer(_version) { + // initialize deployed vault + __GnoErc20Vault_init( + IGnoVaultFactory(msg.sender).vaultAdmin(), + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoErc20VaultInitParams)) + ); + } + + /// @inheritdoc IERC20 + function transfer( + address to, + uint256 amount + ) public virtual override(IERC20, ERC20Upgradeable) returns (bool) { + bool success = super.transfer(to, amount); + _checkOsTokenPosition(msg.sender); + return success; + } + + /// @inheritdoc IERC20 + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual override(IERC20, ERC20Upgradeable) returns (bool) { + bool success = super.transferFrom(from, to, amount); + _checkOsTokenPosition(from); + return success; + } + + /// @inheritdoc IVaultEnterExit + function enterExitQueue( + uint256 shares, + address receiver + ) + public + virtual + override(IVaultEnterExit, VaultEnterExit, VaultOsToken) + returns (uint256 positionTicket) + { + return super.enterExitQueue(shares, receiver); + } + + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, VaultVersion) returns (bytes32) { + return keccak256('GnoErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { + return _version; + } + + /// @inheritdoc VaultState + function _updateExitQueue() + internal + virtual + override(VaultState, VaultToken) + returns (uint256 burnedShares) + { + return super._updateExitQueue(); + } + + /// @inheritdoc VaultState + function _mintShares( + address owner, + uint256 shares + ) internal virtual override(VaultState, VaultToken) { + super._mintShares(owner, shares); + } + + /// @inheritdoc VaultState + function _burnShares( + address owner, + uint256 shares + ) internal virtual override(VaultState, VaultToken) { + super._burnShares(owner, shares); + } + + /** + * @dev Initializes the GnoErc20Vault contract + * @param admin The address of the admin of the Vault + * @param ownMevEscrow The address of the MEV escrow owned by the Vault. Zero address if shared MEV escrow is used. + * @param params The decoded parameters for initializing the GnoErc20Vault contract + */ + function __GnoErc20Vault_init( + address admin, + address ownMevEscrow, + GnoErc20VaultInitParams memory params + ) internal onlyInitializing { + __VaultAdmin_init(admin, params.metadataIpfsHash); + // fee recipient is initially set to admin address + __VaultFee_init(admin, params.feePercent); + __VaultState_init(params.capacity); + __VaultValidators_init(); + __VaultMev_init(ownMevEscrow); + __VaultToken_init(params.name, params.symbol); + __VaultGnoStaking_init(); + } + + /** + * @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/gnosis/GnoGenesisVault.sol b/contracts/vaults/gnosis/GnoGenesisVault.sol new file mode 100644 index 00000000..a5e71863 --- /dev/null +++ b/contracts/vaults/gnosis/GnoGenesisVault.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BUSL-1.1 + +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 {IGnoValidatorsRegistry} from '../../interfaces/IGnoValidatorsRegistry.sol'; +import {IVaultVersion} from '../../interfaces/IVaultVersion.sol'; +import {IGnoPoolEscrow} from '../../interfaces/IGnoPoolEscrow.sol'; +import {IGnoGenesisVault} from '../../interfaces/IGnoGenesisVault.sol'; +import {IRewardGnoToken} from '../../interfaces/IRewardGnoToken.sol'; +import {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol'; +import {Errors} from '../../libraries/Errors.sol'; +import {VaultValidators} from '../modules/VaultValidators.sol'; +import {VaultEnterExit} from '../modules/VaultEnterExit.sol'; +import {VaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultState, IVaultState} from '../modules/VaultState.sol'; +import {GnoVault, IGnoVault} from './GnoVault.sol'; + +/** + * @title GnoGenesisVault + * @author StakeWise + * @notice Defines the Genesis Vault for Gnosis staking migrated from StakeWise v2 + */ +contract GnoGenesisVault is Initializable, GnoVault, IGnoGenesisVault { + // slither-disable-next-line shadowing-state + uint8 private constant _version = 2; + + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + IGnoPoolEscrow private immutable _poolEscrow; + + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + IRewardGnoToken private immutable _rewardGnoToken; + + error InvalidInitialHarvest(); + + /** + * @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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param poolEscrow The address of the pool escrow from StakeWise v2 + * @param rewardGnoToken The address of the rGNO2 token from StakeWise v2 + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + address poolEscrow, + address rewardGnoToken, + uint256 exitingAssetsClaimDelay + ) + GnoVault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + exitingAssetsClaimDelay + ) + { + _poolEscrow = IGnoPoolEscrow(poolEscrow); + _rewardGnoToken = IRewardGnoToken(rewardGnoToken); + } + + /// @inheritdoc IGnoVault + function initialize( + bytes calldata params + ) external virtual override(IGnoVault, GnoVault) reinitializer(_version) { + // initialize deployed vault + (address _admin, GnoVaultInitParams memory initParams) = abi.decode( + params, + (address, GnoVaultInitParams) + ); + // use shared MEV escrow + __GnoVault_init(_admin, address(0), initParams); + emit GenesisVaultCreated( + _admin, + initParams.capacity, + initParams.feePercent, + initParams.metadataIpfsHash + ); + } + + /// @inheritdoc IGnoGenesisVault + function acceptPoolEscrowOwnership() external override { + _checkAdmin(); + _poolEscrow.applyOwnershipTransfer(); + } + + /// @inheritdoc IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, GnoVault) returns (bytes32) { + return keccak256('GnoGenesisVault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, GnoVault) returns (uint8) { + return _version; + } + + /// @inheritdoc IVaultState + function updateState( + IKeeperRewards.HarvestParams calldata harvestParams + ) public override(IVaultState, VaultState) { + bool isCollateralized = IKeeperRewards(_keeper).isCollateralized(address(this)); + + // process total assets delta since last update + (int256 totalAssetsDelta, ) = _harvestAssets(harvestParams); + + if (!isCollateralized) { + // it's the first harvest, deduct rewards accumulated so far in legacy pool + totalAssetsDelta -= SafeCast.toInt256(_rewardGnoToken.totalRewards()); + // the first state update must be with positive delta + if (_poolEscrow.owner() != address(this) || totalAssetsDelta < 0) { + revert InvalidInitialHarvest(); + } + } + + // process total assets delta + _processTotalAssetsDelta(totalAssetsDelta); + } + + /// @inheritdoc IGnoGenesisVault + function migrate(address receiver, uint256 assets) external override returns (uint256 shares) { + if (msg.sender != address(_rewardGnoToken) || _poolEscrow.owner() != address(this)) { + revert Errors.AccessDenied(); + } + + _checkCollateralized(); + _checkHarvested(); + if (receiver == address(0)) revert Errors.ZeroAddress(); + if (assets == 0) revert Errors.InvalidAssets(); + + // calculate amount of shares to mint + shares = convertToShares(assets); + + // update state + _totalAssets += SafeCast.toUint128(assets); + _mintShares(receiver, shares); + + emit Migrated(receiver, assets, shares); + } + + /// @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 = _rewardGnoToken.totalAssets() - _rewardGnoToken.totalPenalty(); + if (legacyPrincipal == 0) { + 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) + ); + _rewardGnoToken.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) + ); + _rewardGnoToken.updateTotalRewards(legacyReward); + // deduct reward from total assets delta + totalAssetsDelta -= legacyReward; + } + + // process total assets delta + super._processTotalAssetsDelta(totalAssetsDelta); + } + + /// @inheritdoc VaultState + function _vaultAssets() + internal + view + virtual + override(VaultState, VaultGnoStaking) + returns (uint256) + { + return + _gnoToken.balanceOf(address(this)) + + IGnoValidatorsRegistry(_validatorsRegistry).withdrawableAmount(address(_poolEscrow)); + } + + /// @inheritdoc VaultGnoStaking + function _pullWithdrawals() internal override { + IGnoValidatorsRegistry(_validatorsRegistry).claimWithdrawal(address(_poolEscrow)); + uint256 escrowAssets = _gnoToken.balanceOf(address(_poolEscrow)); + if (escrowAssets != 0) { + _poolEscrow.withdrawTokens(address(_gnoToken), address(this), escrowAssets); + } + } + + /** + * @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/gnosis/GnoPrivErc20Vault.sol b/contracts/vaults/gnosis/GnoPrivErc20Vault.sol new file mode 100644 index 00000000..7bcf421c --- /dev/null +++ b/contracts/vaults/gnosis/GnoPrivErc20Vault.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoPrivErc20Vault} from '../../interfaces/IGnoPrivErc20Vault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {ERC20Upgradeable} from '../../base/ERC20Upgradeable.sol'; +import {VaultGnoStaking, IVaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultWhitelist} from '../modules/VaultWhitelist.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {GnoErc20Vault, IGnoErc20Vault} from './GnoErc20Vault.sol'; + +/** + * @title GnoPrivErc20Vault + * @author StakeWise + * @notice Defines the Gnosis staking Vault with whitelist and ERC-20 token + */ +contract GnoPrivErc20Vault is Initializable, GnoErc20Vault, VaultWhitelist, IGnoPrivErc20Vault { + // slither-disable-next-line shadowing-state + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + GnoErc20Vault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IGnoErc20Vault + function initialize( + bytes calldata params + ) external virtual override(IGnoErc20Vault, GnoErc20Vault) reinitializer(_version) { + // initialize deployed vault + address _admin = IGnoVaultFactory(msg.sender).vaultAdmin(); + __GnoErc20Vault_init( + _admin, + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoErc20VaultInitParams)) + ); + // whitelister is initially set to admin address + __VaultWhitelist_init(_admin); + } + + /// @inheritdoc IVaultGnoStaking + function deposit( + uint256 assets, + address receiver, + address referrer + ) public virtual override(IVaultGnoStaking, VaultGnoStaking) returns (uint256 shares) { + _checkWhitelist(msg.sender); + _checkWhitelist(receiver); + return super.deposit(assets, receiver, referrer); + } + + /// @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 IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, GnoErc20Vault) returns (bytes32) { + return keccak256('GnoPrivErc20Vault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, GnoErc20Vault) 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. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/vaults/gnosis/GnoPrivVault.sol b/contracts/vaults/gnosis/GnoPrivVault.sol new file mode 100644 index 00000000..f72c23fd --- /dev/null +++ b/contracts/vaults/gnosis/GnoPrivVault.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoPrivVault} from '../../interfaces/IGnoPrivVault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {VaultGnoStaking, IVaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultOsToken, IVaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultWhitelist} from '../modules/VaultWhitelist.sol'; +import {VaultVersion, IVaultVersion} from '../modules/VaultVersion.sol'; +import {GnoVault, IGnoVault} from './GnoVault.sol'; + +/** + * @title GnoPrivVault + * @author StakeWise + * @notice Defines the Gnosis staking Vault with whitelist + */ +contract GnoPrivVault is Initializable, GnoVault, VaultWhitelist, IGnoPrivVault { + // slither-disable-next-line shadowing-state + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + GnoVault( + _keeper, + _vaultsRegistry, + _validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + exitingAssetsClaimDelay + ) + {} + + /// @inheritdoc IGnoVault + function initialize( + bytes calldata params + ) external virtual override(IGnoVault, GnoVault) reinitializer(_version) { + // initialize deployed vault + address _admin = IGnoVaultFactory(msg.sender).vaultAdmin(); + __GnoVault_init( + _admin, + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoVaultInitParams)) + ); + // whitelister is initially set to admin address + __VaultWhitelist_init(_admin); + } + + /// @inheritdoc IVaultGnoStaking + function deposit( + uint256 assets, + address receiver, + address referrer + ) public virtual override(IVaultGnoStaking, VaultGnoStaking) returns (uint256 shares) { + _checkWhitelist(msg.sender); + _checkWhitelist(receiver); + return super.deposit(assets, receiver, referrer); + } + + /// @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 IVaultVersion + function vaultId() public pure virtual override(IVaultVersion, GnoVault) returns (bytes32) { + return keccak256('GnoPrivVault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, GnoVault) 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/gnosis/GnoVault.sol b/contracts/vaults/gnosis/GnoVault.sol new file mode 100644 index 00000000..a6b2df9e --- /dev/null +++ b/contracts/vaults/gnosis/GnoVault.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {IGnoVault} from '../../interfaces/IGnoVault.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.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, IVaultVersion} from '../modules/VaultVersion.sol'; +import {VaultImmutables} from '../modules/VaultImmutables.sol'; +import {VaultState} from '../modules/VaultState.sol'; +import {VaultEnterExit, IVaultEnterExit} from '../modules/VaultEnterExit.sol'; +import {VaultOsToken} from '../modules/VaultOsToken.sol'; +import {VaultGnoStaking} from '../modules/VaultGnoStaking.sol'; +import {VaultMev} from '../modules/VaultMev.sol'; + +/** + * @title GnoVault + * @author StakeWise + * @notice Defines the Gnosis staking Vault + */ +contract GnoVault is + VaultImmutables, + Initializable, + VaultAdmin, + VaultVersion, + VaultFee, + VaultState, + VaultValidators, + VaultEnterExit, + VaultOsToken, + VaultMev, + VaultGnoStaking, + Multicall, + IGnoVault +{ + 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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + * @param exitingAssetsClaimDelay The delay after which the assets can be claimed after exiting from staking + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address _keeper, + address _vaultsRegistry, + address _validatorsRegistry, + address osTokenVaultController, + address osTokenConfig, + address sharedMevEscrow, + address gnoToken, + address xdaiExchange, + uint256 exitingAssetsClaimDelay + ) + VaultImmutables(_keeper, _vaultsRegistry, _validatorsRegistry) + VaultEnterExit(exitingAssetsClaimDelay) + VaultOsToken(osTokenVaultController, osTokenConfig) + VaultMev(sharedMevEscrow) + VaultGnoStaking(gnoToken, xdaiExchange) + { + _disableInitializers(); + } + + /// @inheritdoc IGnoVault + function initialize(bytes calldata params) external virtual override reinitializer(_version) { + // initialize deployed vault + __GnoVault_init( + IGnoVaultFactory(msg.sender).vaultAdmin(), + IGnoVaultFactory(msg.sender).ownMevEscrow(), + abi.decode(params, (GnoVaultInitParams)) + ); + } + + /// @inheritdoc IVaultEnterExit + function enterExitQueue( + uint256 shares, + address receiver + ) + public + virtual + override(IVaultEnterExit, VaultEnterExit, VaultOsToken) + returns (uint256 positionTicket) + { + return super.enterExitQueue(shares, receiver); + } + + /// @inheritdoc VaultVersion + function vaultId() public pure virtual override(IVaultVersion, VaultVersion) returns (bytes32) { + return keccak256('GnoVault'); + } + + /// @inheritdoc IVaultVersion + function version() public pure virtual override(IVaultVersion, VaultVersion) returns (uint8) { + return _version; + } + + /** + * @dev Initializes the GnoVault contract + * @param admin The address of the admin of the Vault + * @param ownMevEscrow The address of the MEV escrow owned by the Vault. Zero address if shared MEV escrow is used. + * @param params The decoded parameters for initializing the GnoVault contract + */ + function __GnoVault_init( + address admin, + address ownMevEscrow, + GnoVaultInitParams memory params + ) internal onlyInitializing { + __VaultAdmin_init(admin, params.metadataIpfsHash); + // fee recipient is initially set to admin address + __VaultFee_init(admin, params.feePercent); + __VaultState_init(params.capacity); + __VaultValidators_init(); + __VaultMev_init(ownMevEscrow); + __VaultGnoStaking_init(); + } + + /** + * @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/gnosis/GnoVaultFactory.sol b/contracts/vaults/gnosis/GnoVaultFactory.sol new file mode 100644 index 00000000..6914e757 --- /dev/null +++ b/contracts/vaults/gnosis/GnoVaultFactory.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import {ERC1967Proxy} from '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol'; +import {IGnoVaultFactory} from '../../interfaces/IGnoVaultFactory.sol'; +import {IGnoVault} from '../../interfaces/IGnoVault.sol'; +import {IVaultsRegistry} from '../../interfaces/IVaultsRegistry.sol'; +import {GnoOwnMevEscrow} from './mev/GnoOwnMevEscrow.sol'; + +/** + * @title GnoVaultFactory + * @author StakeWise + * @notice Factory for deploying Gnosis staking Vaults + */ +contract GnoVaultFactory is IGnoVaultFactory { + uint256 private constant _securityDeposit = 1e9; + + IVaultsRegistry internal immutable _vaultsRegistry; + + IERC20 internal immutable _gnoToken; + + /// @inheritdoc IGnoVaultFactory + address public immutable override implementation; + + /// @inheritdoc IGnoVaultFactory + address public override ownMevEscrow; + + /// @inheritdoc IGnoVaultFactory + address public override vaultAdmin; + + /** + * @dev Constructor + * @param _implementation The implementation address of Vault + * @param vaultsRegistry The address of the VaultsRegistry contract + * @param gnoToken The address of the GNO token + */ + constructor(address _implementation, IVaultsRegistry vaultsRegistry, address gnoToken) { + implementation = _implementation; + _vaultsRegistry = vaultsRegistry; + _gnoToken = IERC20(gnoToken); + } + + /// @inheritdoc IGnoVaultFactory + function createVault( + bytes calldata params, + bool isOwnMevEscrow + ) external override returns (address vault) { + // transfer GNO security deposit to the factory + // see https://github.com/OpenZeppelin/openzeppelin-contracts/issues/3706 + SafeERC20.safeTransferFrom(_gnoToken, msg.sender, address(this), _securityDeposit); + + // create vault + vault = address(new ERC1967Proxy(implementation, '')); + + // approve GNO token for the vault security deposit + _gnoToken.approve(vault, _securityDeposit); + + // create MEV escrow contract if needed + address _mevEscrow; + if (isOwnMevEscrow) { + _mevEscrow = address(new GnoOwnMevEscrow(vault)); + // set MEV escrow contract so that it can be initialized in the Vault + ownMevEscrow = _mevEscrow; + } + + // set admin so that it can be initialized in the Vault + vaultAdmin = msg.sender; + + // initialize Vault + IGnoVault(vault).initialize(params); + + // cleanup MEV escrow contract + if (isOwnMevEscrow) delete ownMevEscrow; + + // cleanup admin + delete vaultAdmin; + + // add vault to the registry + _vaultsRegistry.addVault(vault); + + // emit event + emit VaultCreated(msg.sender, vault, _mevEscrow, params); + } +} diff --git a/contracts/vaults/gnosis/mev/GnoOwnMevEscrow.sol b/contracts/vaults/gnosis/mev/GnoOwnMevEscrow.sol new file mode 100644 index 00000000..31214bfd --- /dev/null +++ b/contracts/vaults/gnosis/mev/GnoOwnMevEscrow.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Address} from '@openzeppelin/contracts/utils/Address.sol'; +import {IOwnMevEscrow} from '../../../interfaces/IOwnMevEscrow.sol'; +import {Errors} from '../../../libraries/Errors.sol'; + +/** + * @title GnoOwnMevEscrow + * @author StakeWise + * @notice Accumulates received MEV. The escrow is owned by the Vault. + */ +contract GnoOwnMevEscrow is IOwnMevEscrow { + /// @inheritdoc IOwnMevEscrow + address payable public immutable override vault; + + /** + * @dev Constructor + * @param _vault The address of the Vault contract + */ + constructor(address _vault) { + // payable is not used but is required for the interface + vault = payable(_vault); + } + + /// @inheritdoc IOwnMevEscrow + function harvest() external returns (uint256) { + if (msg.sender != vault) revert Errors.HarvestFailed(); + + uint256 balance = address(this).balance; + if (balance != 0) { + // transfer all xDAI to the vault + Address.sendValue(vault, balance); + emit Harvested(balance); + } + + // always returns 0 as xDAI must be converted to GNO first + return 0; + } + + /** + * @dev Function for receiving MEV + */ + receive() external payable { + emit MevReceived(msg.value); + } +} diff --git a/contracts/vaults/gnosis/mev/GnoSharedMevEscrow.sol b/contracts/vaults/gnosis/mev/GnoSharedMevEscrow.sol new file mode 100644 index 00000000..ee63e82d --- /dev/null +++ b/contracts/vaults/gnosis/mev/GnoSharedMevEscrow.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {Address} from '@openzeppelin/contracts/utils/Address.sol'; +import {ISharedMevEscrow} from '../../../interfaces/ISharedMevEscrow.sol'; +import {IVaultsRegistry} from '../../../interfaces/IVaultsRegistry.sol'; +import {Errors} from '../../../libraries/Errors.sol'; + +/** + * @title GnoSharedMevEscrow + * @author StakeWise + * @notice Accumulates received MEV. The rewards are shared by multiple Vaults. + */ +contract GnoSharedMevEscrow is ISharedMevEscrow { + IVaultsRegistry private immutable _vaultsRegistry; + + /// @dev Constructor + constructor(address vaultsRegistry) { + _vaultsRegistry = IVaultsRegistry(vaultsRegistry); + } + + /// @inheritdoc ISharedMevEscrow + function harvest(uint256 assets) external override { + if (!_vaultsRegistry.vaults(msg.sender)) revert Errors.HarvestFailed(); + + // transfer xDAI to the vault + Address.sendValue(payable(msg.sender), assets); + emit Harvested(msg.sender, assets); + } + + /** + * @dev Function for receiving MEV + */ + receive() external payable { + emit MevReceived(msg.value); + } +} 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..df3a0aa5 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) { @@ -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,61 @@ 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, positionTicket, 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 + unchecked { + // cannot underflow as totalExitedTickets > positionTicket + exitedTickets = Math.min(exitingTickets, totalExitedTickets - positionTicket); + } + return (exitedTickets, _convertExitTicketsToAssets(exitedTickets)); } /** @@ -155,74 +181,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 V2ExitQueueEntered(user, receiver, positionTicket, shares, 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/VaultGnoStaking.sol b/contracts/vaults/modules/VaultGnoStaking.sol new file mode 100644 index 00000000..8e687ad6 --- /dev/null +++ b/contracts/vaults/modules/VaultGnoStaking.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity =0.8.22; + +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import {SafeCast} from '@openzeppelin/contracts/utils/math/SafeCast.sol'; +import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; +import {ReentrancyGuardUpgradeable} from '@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol'; +import {IGnoValidatorsRegistry} from '../../interfaces/IGnoValidatorsRegistry.sol'; +import {IKeeperRewards} from '../../interfaces/IKeeperRewards.sol'; +import {IXdaiExchange} from '../../interfaces/IXdaiExchange.sol'; +import {IVaultGnoStaking} from '../../interfaces/IVaultGnoStaking.sol'; +import {Errors} from '../../libraries/Errors.sol'; +import {VaultAdmin} from './VaultAdmin.sol'; +import {VaultState} from './VaultState.sol'; +import {VaultValidators} from './VaultValidators.sol'; +import {VaultEnterExit} from './VaultEnterExit.sol'; + +/** + * @title VaultGnoStaking + * @author StakeWise + * @notice Defines the Gnosis staking functionality for the Vault + */ +abstract contract VaultGnoStaking is + Initializable, + ReentrancyGuardUpgradeable, + VaultAdmin, + VaultState, + VaultValidators, + VaultEnterExit, + IVaultGnoStaking +{ + uint256 private constant _securityDeposit = 1e9; + + IERC20 internal immutable _gnoToken; + address private immutable _xdaiExchange; + + address private _xdaiManager; + + /** + * @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 gnoToken The address of the GNO token + * @param xdaiExchange The address of the xDAI exchange + */ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor(address gnoToken, address xdaiExchange) { + _gnoToken = IERC20(gnoToken); + _xdaiExchange = xdaiExchange; + } + + /// @inheritdoc IVaultGnoStaking + function xdaiManager() public view override returns (address) { + // SLOAD to memory + address xdaiManager_ = _xdaiManager; + // if xdaiManager is not set, use admin address + return xdaiManager_ == address(0) ? admin : xdaiManager_; + } + + /// @inheritdoc IVaultGnoStaking + function deposit( + uint256 assets, + address receiver, + address referrer + ) public virtual override nonReentrant returns (uint256 shares) { + // withdraw GNO tokens from the user + SafeERC20.safeTransferFrom(_gnoToken, msg.sender, address(this), assets); + shares = _deposit(receiver, assets, referrer); + } + + /// @inheritdoc IVaultGnoStaking + function swapXdaiToGno( + uint256 amount, + uint256 limit, + uint256 deadline + ) external override nonReentrant returns (uint256 assets) { + if (msg.sender != xdaiManager()) revert Errors.AccessDenied(); + + // check and swap assets + uint256 assetsBefore = _vaultAssets(); + assets = IXdaiExchange(_xdaiExchange).swap{value: amount}(limit, deadline); + if (_vaultAssets() < assetsBefore + limit) { + revert Errors.InvalidAssets(); + } + + // update total assets + _processTotalAssetsDelta(SafeCast.toInt256(assets)); + emit XdaiSwapped(amount, assets); + } + + /// @inheritdoc IVaultGnoStaking + function setXdaiManager(address xdaiManager_) external override { + _checkAdmin(); + // update xdaiManager address + _xdaiManager = xdaiManager_; + emit XdaiManagerUpdated(msg.sender, xdaiManager_); + } + + /** + * @dev Function for receiving xDAI + */ + receive() external payable {} + + /// @inheritdoc VaultValidators + function _registerSingleValidator(bytes calldata validator) internal virtual override { + // pull withdrawals from the deposit contract + _pullWithdrawals(); + + // register single validator + bytes calldata publicKey = validator[:48]; + _gnoToken.approve(_validatorsRegistry, _validatorDeposit()); + IGnoValidatorsRegistry(_validatorsRegistry).deposit( + publicKey, + _withdrawalCredentials(), + validator[48:144], + bytes32(validator[144:_validatorLength]), + _validatorDeposit() + ); + + emit ValidatorRegistered(publicKey); + } + + /// @inheritdoc VaultValidators + function _registerMultipleValidators( + bytes calldata validators, + uint256[] calldata indexes + ) internal virtual override returns (bytes32[] memory leaves) { + // pull withdrawals from the deposit contract + _pullWithdrawals(); + + // define leaves + uint256 validatorsCount = indexes.length; + leaves = new bytes32[](validatorsCount); + + // variables used for batch deposit + bytes memory publicKeys; + bytes memory signatures; + bytes32[] memory depositDataRoots = new bytes32[](validatorsCount); + + { + // SLOAD to memory + uint256 currentValIndex = validatorIndex; + + // process validators + uint256 startIndex; + uint256 endIndex; + bytes calldata validator; + for (uint256 i = 0; i < validatorsCount; i++) { + endIndex += _validatorLength; + validator = validators[startIndex:endIndex]; + leaves[indexes[i]] = keccak256( + bytes.concat(keccak256(abi.encode(validator, currentValIndex))) + ); + publicKeys = bytes.concat(publicKeys, validator[:48]); + signatures = bytes.concat(signatures, validator[48:144]); + depositDataRoots[i] = bytes32(validator[144:_validatorLength]); + startIndex = endIndex; + unchecked { + // cannot realistically overflow + ++currentValIndex; + } + emit ValidatorRegistered(validator[:48]); + } + } + + // register validators batch + _gnoToken.approve(_validatorsRegistry, _validatorDeposit() * validatorsCount); + IGnoValidatorsRegistry(_validatorsRegistry).batchDeposit( + publicKeys, + _withdrawalCredentials(), + signatures, + depositDataRoots + ); + } + + /// @inheritdoc VaultState + function _vaultAssets() internal view virtual override returns (uint256) { + return + _gnoToken.balanceOf(address(this)) + + IGnoValidatorsRegistry(_validatorsRegistry).withdrawableAmount(address(this)); + } + + /// @inheritdoc VaultEnterExit + function _transferVaultAssets( + address receiver, + uint256 assets + ) internal virtual override nonReentrant { + if (assets > _gnoToken.balanceOf(address(this))) { + _pullWithdrawals(); + } + SafeERC20.safeTransfer(_gnoToken, receiver, assets); + } + + /// @inheritdoc VaultValidators + function _validatorDeposit() internal pure override returns (uint256) { + return 1 ether; + } + + /** + * @dev Pulls assets from withdrawal contract + */ + function _pullWithdrawals() internal virtual { + IGnoValidatorsRegistry(_validatorsRegistry).claimWithdrawal(address(this)); + } + + /** + * @dev Initializes the VaultGnoStaking contract + */ + function __VaultGnoStaking_init() internal onlyInitializing { + __ReentrancyGuard_init(); + + _deposit(address(this), _securityDeposit, address(0)); + // see https://github.com/OpenZeppelin/openzeppelin-contracts/issues/3706 + SafeERC20.safeTransferFrom(_gnoToken, msg.sender, address(this), _securityDeposit); + } + + /** + * @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/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..55fea244 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'; /** @@ -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, diff --git a/contracts/vaults/modules/VaultState.sol b/contracts/vaults/modules/VaultState.sol index 64e38695..8fc26f0d 100644 --- a/contracts/vaults/modules/VaultState.sol +++ b/contracts/vaults/modules/VaultState.sol @@ -33,6 +33,11 @@ abstract contract VaultState is VaultImmutables, Initializable, VaultFee, IVault uint256 private _capacity; + /// @inheritdoc IVaultState + uint128 public override totalExitingAssets; + uint128 internal _totalExitingTickets; + uint256 internal _totalExitedTickets; + /// @inheritdoc IVaultState function totalShares() external view override returns (uint256) { return _totalShares; @@ -74,7 +79,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; } } @@ -92,7 +99,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(); @@ -102,15 +109,38 @@ 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) { - // add penalty to total assets - newTotalAssets -= uint256(-totalAssetsDelta); + uint256 penalty = uint256(-totalAssetsDelta); + + // SLOAD to memory + uint256 _totalExitingAssets = totalExitingAssets; + if (_totalExitingAssets > 0) { + // apply penalty to exiting assets + uint256 exitingAssetsPenalty = Math.mulDiv( + penalty, + _totalExitingAssets, + _totalExitingAssets + newTotalAssets + ); + + // apply penalty to total exiting assets + unchecked { + // cannot underflow as exitingAssetsPenalty <= penalty + penalty -= exitingAssetsPenalty; + // cannot underflow as exitingAssetsPenalty <= _totalExitingAssets + totalExitingAssets = SafeCast.toUint128(_totalExitingAssets - exitingAssetsPenalty); + } + } - // update state - _totalAssets = SafeCast.toUint128(newTotalAssets); + // subtract penalty from total assets (excludes exiting assets) + if (penalty > 0) { + _totalAssets = SafeCast.toUint128(newTotalAssets - penalty); + } return; } @@ -234,6 +264,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 +314,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/VaultWhitelist.sol b/contracts/vaults/modules/VaultWhitelist.sol index 3938035f..54554680 100644 --- a/contracts/vaults/modules/VaultWhitelist.sol +++ b/contracts/vaults/modules/VaultWhitelist.sol @@ -22,7 +22,9 @@ abstract contract VaultWhitelist is Initializable, VaultAdmin, IVaultWhitelist { /// @inheritdoc IVaultWhitelist function updateWhitelist(address account, bool approved) external 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/deployments/chiado.json b/deployments/chiado.json new file mode 100644 index 00000000..0ea74636 --- /dev/null +++ b/deployments/chiado.json @@ -0,0 +1,18 @@ +{ + "VaultsRegistry": "0x384B388A040C6b32c9B5927aB25891F2bAd4E5f7", + "Keeper": "0x96Bd48CD98D2CC602b93A2BBbF05d7eEB21CdE8E", + "GnoGenesisVault": "0xA2600eB0A0cd1DD80b090Fc2D319516CDBF5d721", + "GnoVaultFactory": "0xe79b759eF5835776b5A55A55552b86b57f66aA0E", + "GnoPrivVaultFactory": "0xd65846faa8fB7C22777869E9eDDB13F4D0DeD3be", + "GnoBlocklistVaultFactory": "0x765a1B647cd2020FD08CDD810CB1D00Eeb02E151", + "GnoErc20VaultFactory": "0xf9706bd4540e59B1D3Bd77b5B9E55C2486a7a145", + "GnoPrivErc20VaultFactory": "0x352FA9D876910D51A1Ed309605c899a3D93773F1", + "GnoBlocklistErc20VaultFactory": "0x4e97Eca0aae622d49cc0ceC0e50a9880b1D6abD5", + "SharedMevEscrow": "0xc7Eb19FcB20291A959ba90D11d2c6Fe8Db1F66b9", + "OsToken": "0x555f0C927E853aEa52f88ca9f5a7b4f215cBe039", + "OsTokenConfig": "0x9a3d84D8FE20cDaBe8AeB74296C10C1DbED3dF81", + "OsTokenVaultController": "0xf99dc8Df363be34AbA6A4EAdE77c9d61e85b126F", + "PriceFeed": "0xf22F9Dba5281181D71F3EA42A8AfA13AF6B3E700", + "RewardSplitterFactory": "0xE4480EcE26B697D42952a2380E42a88510020711", + "StakeWiseToken": "0x460d2c6c3254809949a7d0b4646ce15F77e9c545" +} 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/hardhat.config.ts b/hardhat.config.ts index 7ffbf386..c5c99ed2 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -74,6 +74,7 @@ const config: HardhatUserConfig = { networks: { holesky: getCommonNetworkConfig(Networks.holesky), mainnet: getCommonNetworkConfig(Networks.mainnet), + chiado: getCommonNetworkConfig(Networks.chiado), hardhat: { blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT, gas: DEFAULT_BLOCK_GAS_LIMIT, diff --git a/helpers/constants.ts b/helpers/constants.ts index 48785de7..89dca870 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -1,6 +1,6 @@ import { NetworkConfig, Networks } from './types' import { parseEther } from 'ethers' -import { MAX_UINT256 } from '../test/shared/constants' +import { MAX_UINT256, ZERO_BYTES32 } from '../test/shared/constants' const MAX_UINT16 = 2n ** 16n - 1n @@ -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% }, @@ -133,59 +133,70 @@ export const NETWORKS: { liquidityCommittee: '0x189Cb93839AD52b5e955ddA254Ed7212ae1B1f61', swiseToken: '0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2', }, -} + [Networks.chiado]: { + url: process.env.NETWORK_RPC_URL || '', + chainId: 10200, -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', + governor: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', + validatorsRegistry: '0xb97036A26259B7147018913bD58a774cf91acf25', + securityDeposit: 1000000000n, // 1 gwei of GNO + exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours + + // Keeper + oracles: [ + '0xf1a2f8E2FaE384566Fe10f9a960f52fe4a103737', + '0xF1091485531122c2cd0Beb6fD998FBCcCf42b38C', + '0x51182c9B66F5Cb2394511006851aE9b1Ea7f1B5D', + '0x675eD17F58b15CD2C31F6d9bfb0b4DfcCA264eC1', + '0x6bAfFEE3c8B59E5bA19c26Cd409B2a232abb57Cb', + '0x36a2E8FF08f801caB399eab2fEe9E6A8C49A9C2A', + '0x3EC6676fa4D07C1f31d088ae1DE96240eC56D1D9', + '0x893e1c16fE47DF676Fd344d44c074096675B6aF6', + '0x3eEC4A51cbB2De4e8Cc6c9eE859Ad16E8a8693FC', + '0x9772Ef6AbC2Dfd879ebd88aeAA9Cf1e69a16fCF4', + '0x18991d6F877eF0c0920BFF9B14D994D80d2E7B0c', + ], + rewardsDelay: 12 * 60 * 60, // 12 hours + rewardsMinOracles: 6, + validatorsMinOracles: 6, + maxAvgRewardPerSecond: MAX_UINT256, // unlimited + oraclesConfigIpfsHash: 'QmNP7hT3Q2YB3kPpNKU9orthkeLvZWQpUi8Gf8PQDLVNJm', + + // OsToken + treasury: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', + osTokenFeePercent: 1000, // 10 % + osTokenCapacity: parseEther('200000'), // 200k osGNO + osTokenName: 'Staked GNO', + osTokenSymbol: 'osGNO', + + // OsTokenConfig + redeemFromLtvPercent: MAX_UINT16, // disable redeems + redeemToLtvPercent: MAX_UINT16, // disable redeems + liqThresholdPercent: 6600, // 66% + liqBonusPercent: 10100, // 101% + ltvPercent: 6400, // 64% + + // GnoGenesisVault + genesisVault: { + admin: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6', + poolEscrow: '0x3c5634a5437A394353F49fe04FE5db11961c5c2D', + rewardToken: '0xfe076029B7D46fbe2ad4B9CBf377aA10B309e560', + capacity: parseEther('200000'), // 200k GNO + feePercent: 2000, // 20% }, - { - inputs: [{ internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }], - name: 'supportsInterface', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'pure', - type: 'function', + priceFeedDescription: 'osGNO/GNO', + + // Gnosis data + gnosis: { + gnoToken: '0x19C653Da7c37c66208fbfbE8908A5051B57b4C70', + balancerVault: '0x8b6c2C9E09c6022780D164F3cFd882808b8bDBF0', + balancerPoolId: ZERO_BYTES32, }, - ], - bytecode: - '0x608060405234801561001057600080fd5b5060005b601f8110156101025760026021826020811061002c57fe5b01546021836020811061003b57fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106100925780518252601f199092019160209182019101610073565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa1580156100d1573d6000803e3d6000fd5b5050506040513d60208110156100e657600080fd5b5051602160018301602081106100f857fe5b0155600101610014565b506118d680620001136000396000f3fe60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033', + + // Cumulative MerkleDrop + liquidityCommittee: '0x0000000000000000000000000000000000000000', + swiseToken: '0x0000000000000000000000000000000000000000', + }, } export const MAINNET_FORK = { diff --git a/helpers/types.ts b/helpers/types.ts index 55b0b41b..25421787 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -3,6 +3,7 @@ export type ThenArg = T extends PromiseLike ? U : T export enum Networks { mainnet = 'mainnet', holesky = 'holesky', + chiado = 'chiado', } export type NetworkConfig = { @@ -40,19 +41,26 @@ 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 metadataIpfsHash: string } + // Gnosis data + gnosis?: { + gnoToken: string + balancerVault: string + balancerPoolId: string + } + // PriceFeed priceFeedDescription: string diff --git a/helpers/utils.ts b/helpers/utils.ts index ad1a13c2..e17afdd2 100644 --- a/helpers/utils.ts +++ b/helpers/utils.ts @@ -6,9 +6,10 @@ export async function deployContract( hre: HardhatRuntimeEnvironment, contractName: string, constructorArgs: any[], - path?: string + path?: string, + options?: any ): Promise { - const contract = await hre.ethers.deployContract(contractName, constructorArgs) + const contract = await hre.ethers.deployContract(contractName, constructorArgs, options) await contract.waitForDeployment() const contractAddress = await contract.getAddress() diff --git a/package.json b/package.json index 59a75d14..b729d4f1 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "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", + "full-deploy:chiado": "hardhat gno-full-deploy --network chiado" }, "repository": { "type": "git", diff --git a/tasks/eth-full-deploy-local.ts b/tasks/eth-full-deploy-local.ts index b1b39d91..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) @@ -211,34 +223,44 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ const foxVaultFactory = await ethers.getContractFactory('EthFoxVault') await simulateDeployImpl(hre, foxVaultFactory, { constructorArgs }, foxVaultImplAddress) - // Deploy EthFoxVault proxy - proxy = await deployContract(hre, 'ERC1967Proxy', [foxVaultImplAddress, '0x']) - const foxVaultAddress = await proxy.getAddress() - const foxVault = foxVaultFactory.attach(foxVaultAddress) + const foxVaultAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: (await ethers.provider.getTransactionCount(deployer.address)) + 1, + }) - // Initialize EthFoxVault + // Deploy ownMevEscrow for EthFoxVault const ownMevEscrowFactory = await ethers.getContractFactory('OwnMevEscrow') const ownMevEscrow = await ownMevEscrowFactory.deploy(foxVaultAddress) - await callContract( - foxVault.initialize( - ethers.AbiCoder.defaultAbiCoder().encode( - [ - 'tuple(address admin, address ownMevEscrow, uint256 capacity, uint16 feePercent, string metadataIpfsHash)', - ], - [ - [ - networkConfig.foxVault.admin, - await ownMevEscrow.getAddress(), - networkConfig.foxVault.capacity, - networkConfig.foxVault.feePercent, - networkConfig.foxVault.metadataIpfsHash, - ], - ] - ), - { value: networkConfig.securityDeposit } - ) + + // Deploy EthFoxVault proxy + const initCall = ethers.AbiCoder.defaultAbiCoder().encode( + [ + 'tuple(address admin, address ownMevEscrow, uint256 capacity, uint16 feePercent, string metadataIpfsHash)', + ], + [ + [ + networkConfig.foxVault.admin, + await ownMevEscrow.getAddress(), + networkConfig.foxVault.capacity, + networkConfig.foxVault.feePercent, + networkConfig.foxVault.metadataIpfsHash, + ], + ] ) + proxy = await deployContract( + hre, + 'ERC1967Proxy', + [foxVaultImplAddress, foxVaultFactory.interface.encodeFunctionData('initialize', [initCall])], + undefined, + { + value: networkConfig.securityDeposit, + } + ) + if ((await proxy.getAddress()) !== foxVaultAddress) { + throw new Error('EthFoxVault address mismatch') + } + await callContract(vaultsRegistry.addVault(foxVaultAddress)) console.log('Added EthFoxVault to VaultsRegistry') @@ -277,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, @@ -301,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 614d722c..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( @@ -244,39 +255,45 @@ task('eth-full-deploy', 'deploys StakeWise V3 for Ethereum').setAction(async (ta const foxVaultFactory = await ethers.getContractFactory('EthFoxVault') await simulateDeployImpl(hre, foxVaultFactory, { constructorArgs }, foxVaultImplAddress) - // Deploy EthFoxVault proxy - proxy = await deployContract( - hre, - 'ERC1967Proxy', - [foxVaultImplAddress, '0x'], - '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy' - ) - const foxVaultAddress = await proxy.getAddress() - const foxVault = foxVaultFactory.attach(foxVaultAddress) + // calculate EthFoxVault address + const foxVaultAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: (await ethers.provider.getTransactionCount(deployer.address)) + 1, + }) - // Initialize EthFoxVault + // Deploy OwnMevEscrow for EthFoxVault const ownMevEscrowFactory = await ethers.getContractFactory('OwnMevEscrow') const ownMevEscrow = await ownMevEscrowFactory.deploy(foxVaultAddress) - await callContract( - foxVault.initialize( - ethers.AbiCoder.defaultAbiCoder().encode( - [ - 'tuple(address admin, address ownMevEscrow, uint256 capacity, uint16 feePercent, string metadataIpfsHash)', - ], - [ - [ - networkConfig.foxVault.admin, - await ownMevEscrow.getAddress(), - networkConfig.foxVault.capacity, - networkConfig.foxVault.feePercent, - networkConfig.foxVault.metadataIpfsHash, - ], - ] - ), - { value: networkConfig.securityDeposit } - ) + + // Deploy and initialize EthFoxVault proxy + const initCall = ethers.AbiCoder.defaultAbiCoder().encode( + [ + 'tuple(address admin, address ownMevEscrow, uint256 capacity, uint16 feePercent, string metadataIpfsHash)', + ], + [ + [ + networkConfig.foxVault.admin, + await ownMevEscrow.getAddress(), + networkConfig.foxVault.capacity, + networkConfig.foxVault.feePercent, + networkConfig.foxVault.metadataIpfsHash, + ], + ] ) + proxy = await deployContract( + hre, + 'ERC1967Proxy', + [foxVaultImplAddress, foxVaultFactory.interface.encodeFunctionData('initialize', [initCall])], + '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy', + { + value: networkConfig.securityDeposit, + } + ) + if ((await proxy.getAddress()) !== foxVaultAddress) { + throw new Error('EthFoxVault address mismatch') + } + await callContract(vaultsRegistry.addVault(foxVaultAddress)) console.log('Added EthFoxVault to VaultsRegistry') @@ -328,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/tasks/gno-full-deploy.ts b/tasks/gno-full-deploy.ts new file mode 100644 index 00000000..6a4f9461 --- /dev/null +++ b/tasks/gno-full-deploy.ts @@ -0,0 +1,349 @@ +import fs from 'fs' +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 { NETWORKS } from '../helpers/constants' +import { NetworkConfig } from '../helpers/types' + +const DEPLOYMENTS_DIR = 'deployments' + +task('gno-full-deploy', 'deploys StakeWise V3 for Gnosis').setAction(async (taskArgs, hre) => { + const ethers = hre.ethers + const networkName = hre.network.name + const networkConfig: NetworkConfig = NETWORKS[networkName] + const deployer = await ethers.provider.getSigner() + + if (networkConfig.gnosis === undefined) { + throw new Error('Gnosis data is required for this network') + } + + // Create the signer for the mnemonic, connected to the provider with hardcoded fee data + console.log('Deploying StakeWise V3 for Gnosis to', networkName, 'from', deployer.address) + + // deploy VaultsRegistry + const vaultsRegistry = await deployContract( + hre, + 'VaultsRegistry', + [], + 'contracts/vaults/VaultsRegistry.sol:VaultsRegistry' + ) + const vaultsRegistryAddress = await vaultsRegistry.getAddress() + + // deploy SharedMevEscrow + const sharedMevEscrow = await deployContract( + hre, + 'GnoSharedMevEscrow', + [vaultsRegistryAddress], + 'contracts/vaults/gnosis/mev/GnoSharedMevEscrow.sol:GnoSharedMevEscrow' + ) + const sharedMevEscrowAddress = await sharedMevEscrow.getAddress() + + // calculate osToken and keeper addresses + const osTokenAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: (await ethers.provider.getTransactionCount(deployer.address)) + 1, + }) + const keeperAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: (await ethers.provider.getTransactionCount(deployer.address)) + 2, + }) + + // deploy OsTokenVaultController + const osTokenVaultController = await deployContract( + hre, + 'OsTokenVaultController', + [ + keeperAddress, + vaultsRegistryAddress, + osTokenAddress, + networkConfig.treasury, + networkConfig.governor, + networkConfig.osTokenFeePercent, + networkConfig.osTokenCapacity, + ], + 'contracts/osToken/OsTokenVaultController.sol:OsTokenVaultController' + ) + const osTokenVaultControllerAddress = await osTokenVaultController.getAddress() + + // Deploy OsToken + const osToken = await deployContract( + hre, + 'OsToken', + [ + networkConfig.governor, + osTokenVaultControllerAddress, + networkConfig.osTokenName, + networkConfig.osTokenSymbol, + ], + 'contracts/osToken/OsToken.sol:OsToken' + ) + if ((await osToken.getAddress()) !== osTokenAddress) { + throw new Error('OsToken address mismatch') + } + + // Deploy Keeper + const keeper = await deployContract( + hre, + 'Keeper', + [ + sharedMevEscrowAddress, + vaultsRegistryAddress, + osTokenVaultControllerAddress, + networkConfig.rewardsDelay, + networkConfig.maxAvgRewardPerSecond, + networkConfig.validatorsRegistry, + ], + 'contracts/keeper/Keeper.sol:Keeper' + ) + if ((await keeper.getAddress()) !== keeperAddress) { + throw new Error('Keeper address mismatch') + } + + // Configure Keeper + for (let i = 0; i < networkConfig.oracles.length; i++) { + const oracleAddr = networkConfig.oracles[i] + await callContract(keeper.addOracle(oracleAddr)) + console.log('Added oracle', oracleAddr) + } + await callContract(keeper.updateConfig(networkConfig.oraclesConfigIpfsHash)) + console.log('Updated oracles config to', networkConfig.oraclesConfigIpfsHash) + + await callContract(keeper.setRewardsMinOracles(networkConfig.rewardsMinOracles)) + console.log('Set rewards min oracles to', networkConfig.rewardsMinOracles) + + await callContract(keeper.setValidatorsMinOracles(networkConfig.validatorsMinOracles)) + console.log('Set validators min oracles to', networkConfig.validatorsMinOracles) + + // Deploy OsTokenConfig + const osTokenConfig = await deployContract( + hre, + 'OsTokenConfig', + [ + networkConfig.governor, + { + redeemFromLtvPercent: networkConfig.redeemFromLtvPercent, + redeemToLtvPercent: networkConfig.redeemToLtvPercent, + liqThresholdPercent: networkConfig.liqThresholdPercent, + liqBonusPercent: networkConfig.liqBonusPercent, + ltvPercent: networkConfig.ltvPercent, + }, + ], + 'contracts/osToken/OsTokenConfig.sol:OsTokenConfig' + ) + const osTokenConfigAddress = await osTokenConfig.getAddress() + + // Deploy XdaiExchange implementation + const xdaiExchangeConstructorArgs = [ + networkConfig.gnosis.gnoToken, + networkConfig.gnosis.balancerPoolId, + networkConfig.gnosis.balancerVault, + vaultsRegistryAddress, + ] + const xDaiExchangeImpl = await deployContract( + hre, + 'XdaiExchange', + xdaiExchangeConstructorArgs, + 'contracts/misc/XdaiExchange.sol:XdaiExchange' + ) + const xDaiExchangeImplAddress = await xDaiExchangeImpl.getAddress() + const xDaiExchangeFactory = await ethers.getContractFactory('XdaiExchange') + await simulateDeployImpl( + hre, + xDaiExchangeFactory, + { constructorArgs: xdaiExchangeConstructorArgs }, + xDaiExchangeImplAddress + ) + + // Deploy XdaiExchange proxy + let proxy = await deployContract( + hre, + 'ERC1967Proxy', + [xDaiExchangeImplAddress, '0x'], + '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy' + ) + const xdaiExchangeAddress = await proxy.getAddress() + const xdaiExchange = xDaiExchangeFactory.attach(xdaiExchangeAddress) + + // Initialize XdaiExchange + await callContract(xdaiExchange.initialize(networkConfig.governor)) + + const factories: string[] = [] + for (const vaultType of [ + 'GnoVault', + 'GnoPrivVault', + 'GnoErc20Vault', + 'GnoBlocklistVault', + 'GnoPrivErc20Vault', + 'GnoBlocklistErc20Vault', + ]) { + // Deploy Vault Implementation + const constructorArgs = [ + keeperAddress, + vaultsRegistryAddress, + networkConfig.validatorsRegistry, + osTokenVaultControllerAddress, + osTokenConfigAddress, + sharedMevEscrowAddress, + networkConfig.gnosis.gnoToken, + xdaiExchangeAddress, + networkConfig.exitedAssetsClaimDelay, + ] + const vaultImpl = await deployContract( + hre, + vaultType, + constructorArgs, + `contracts/vaults/gnosis/${vaultType}.sol:${vaultType}` + ) + const vaultImplAddress = await vaultImpl.getAddress() + await simulateDeployImpl( + hre, + await ethers.getContractFactory(vaultType), + { constructorArgs }, + vaultImplAddress + ) + + // Deploy Vault Factory + const vaultFactory = await deployContract( + hre, + 'GnoVaultFactory', + [vaultImplAddress, vaultsRegistryAddress, networkConfig.gnosis.gnoToken], + 'contracts/vaults/gnosis/GnoVaultFactory.sol:GnoVaultFactory' + ) + const vaultFactoryAddress = await vaultFactory.getAddress() + + // Add factory to registry + await callContract(vaultsRegistry.addFactory(vaultFactoryAddress)) + console.log(`Added ${vaultType}Factory to VaultsRegistry`) + + // Add implementation to registry + await callContract(vaultsRegistry.addVaultImpl(vaultImplAddress)) + console.log(`Added ${vaultType} implementation to VaultsRegistry`) + factories.push(vaultFactoryAddress) + } + + // Deploy GnoGenesisVault implementation + const genesisVaultConstructorArgs = [ + keeperAddress, + vaultsRegistryAddress, + networkConfig.validatorsRegistry, + osTokenVaultControllerAddress, + osTokenConfigAddress, + sharedMevEscrowAddress, + networkConfig.gnosis.gnoToken, + xdaiExchangeAddress, + networkConfig.genesisVault.poolEscrow, + networkConfig.genesisVault.rewardToken, + networkConfig.exitedAssetsClaimDelay, + ] + const genesisVaultImpl = await deployContract( + hre, + 'GnoGenesisVault', + genesisVaultConstructorArgs, + 'contracts/vaults/gnosis/GnoGenesisVault.sol:GnoGenesisVault' + ) + const genesisVaultImplAddress = await genesisVaultImpl.getAddress() + const genesisVaultFactory = await ethers.getContractFactory('GnoGenesisVault') + await simulateDeployImpl( + hre, + genesisVaultFactory, + { constructorArgs: genesisVaultConstructorArgs }, + genesisVaultImplAddress + ) + + // Deploy GnoGenesisVault proxy + proxy = await deployContract( + hre, + 'ERC1967Proxy', + [genesisVaultImplAddress, '0x'], + '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy' + ) + const genesisVaultAddress = await proxy.getAddress() + const genesisVault = genesisVaultFactory.attach(genesisVaultAddress) + + // Initialize GnoGenesisVault + const erc20TokenFactory = await ethers.getContractFactory('ERC20Mock') + const erc20Token = erc20TokenFactory.attach(networkConfig.gnosis.gnoToken) + await callContract(erc20Token.approve(genesisVaultAddress, networkConfig.securityDeposit)) + await callContract( + genesisVault.initialize( + ethers.AbiCoder.defaultAbiCoder().encode( + ['address', 'tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)'], + [ + networkConfig.genesisVault.admin, + [networkConfig.genesisVault.capacity, networkConfig.genesisVault.feePercent, ''], + ] + ) + ) + ) + + await callContract(vaultsRegistry.addVault(genesisVaultAddress)) + console.log('Added GnoGenesisVault to VaultsRegistry') + + await callContract(vaultsRegistry.addVaultImpl(genesisVaultImplAddress)) + console.log(`Added GnoGenesisVault implementation to VaultsRegistry`) + + // Deploy PriceFeed + const priceFeed = await deployContract( + hre, + 'PriceFeed', + [osTokenVaultControllerAddress, networkConfig.priceFeedDescription], + 'contracts/osToken/PriceFeed.sol:PriceFeed' + ) + const priceFeedAddress = await priceFeed.getAddress() + + // Deploy RewardSplitter Implementation + const rewardSplitterImpl = await deployContract( + hre, + 'RewardSplitter', + [], + 'contracts/misc/RewardSplitter.sol:RewardSplitter' + ) + const rewardSplitterImplAddress = await rewardSplitterImpl.getAddress() + + // Deploy RewardSplitter factory + const rewardSplitterFactory = await deployContract( + hre, + 'RewardSplitterFactory', + [rewardSplitterImplAddress], + 'contracts/misc/RewardSplitterFactory.sol:RewardSplitterFactory' + ) + const rewardSplitterFactoryAddress = await rewardSplitterFactory.getAddress() + + // transfer ownership to governor + await callContract(vaultsRegistry.initialize(networkConfig.governor)) + console.log('VaultsRegistry ownership transferred to', networkConfig.governor) + + await callContract(keeper.initialize(networkConfig.governor)) + console.log('Keeper ownership transferred to', networkConfig.governor) + + // Save the addresses + const addresses = { + VaultsRegistry: vaultsRegistryAddress, + Keeper: keeperAddress, + GnoGenesisVault: genesisVaultAddress, + GnoVaultFactory: factories[0], + GnoPrivVaultFactory: factories[1], + GnoBlocklistVaultFactory: factories[2], + GnoErc20VaultFactory: factories[3], + GnoPrivErc20VaultFactory: factories[4], + GnoBlocklistErc20VaultFactory: factories[5], + SharedMevEscrow: sharedMevEscrowAddress, + OsToken: osTokenAddress, + OsTokenConfig: osTokenConfigAddress, + OsTokenVaultController: osTokenVaultControllerAddress, + PriceFeed: priceFeedAddress, + RewardSplitterFactory: rewardSplitterFactoryAddress, + } + const json = JSON.stringify(addresses, null, 2) + const fileName = `${DEPLOYMENTS_DIR}/${networkName}.json` + + if (!fs.existsSync(DEPLOYMENTS_DIR)) { + fs.mkdirSync(DEPLOYMENTS_DIR) + } + + fs.writeFileSync(fileName, json, 'utf-8') + console.log('Saved to', fileName) + + console.log('NB! Commit and accept StakeWise V2 PoolEscrow ownership to GnoGenesisVault') +}) diff --git a/test/EthBlocklistErc20Vault.spec.ts b/test/EthBlocklistErc20Vault.spec.ts new file mode 100644 index 00000000..964da341 --- /dev/null +++ b/test/EthBlocklistErc20Vault.spec.ts @@ -0,0 +1,207 @@ +import { ethers } from 'hardhat' +import { Contract, Signer, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + EthBlocklistErc20Vault, + IKeeperRewards, + Keeper, + OsTokenVaultController, +} 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) + }) + }) +}) diff --git a/test/EthBlocklistVault.spec.ts b/test/EthBlocklistVault.spec.ts new file mode 100644 index 00000000..51e93812 --- /dev/null +++ b/test/EthBlocklistVault.spec.ts @@ -0,0 +1,168 @@ +import { ethers } from 'hardhat' +import { Contract, Signer, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + EthBlocklistVault, + IKeeperRewards, + Keeper, + OsTokenVaultController, +} 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) + }) + }) +}) diff --git a/test/EthErc20Vault.spec.ts b/test/EthErc20Vault.spec.ts index 9984a6d4..441667d4 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 } @@ -152,20 +135,35 @@ 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, 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) + .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) + 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 e26668b3..f1649753 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', () => { @@ -215,21 +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, '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) - expect(await vault.getShares(sender.address)).to.eq(0) + await expect(tx).to.not.emit(vault, 'V2ExitQueueEntered') await snapshotGasCost(tx) }) @@ -243,8 +229,9 @@ 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/EthGenesisVault.spec.ts b/test/EthGenesisVault.spec.ts index 35141148..4ee10c43 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 () => { @@ -84,7 +90,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 +102,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', () => { @@ -231,11 +221,11 @@ describe('EthGenesisVault', () => { }) }) - it('pulls assets on claim exited assets', async () => { + it('pulls withdrawals on claim exited assets', async () => { 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,9 +254,6 @@ 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) @@ -279,38 +266,7 @@ describe('EthGenesisVault', () => { 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 () => { + it('pulls withdrawals on single validator registration', async () => { await acceptPoolEscrowOwnership() await collatEthVault() const validatorDeposit = ethers.parseEther('32') @@ -329,7 +285,7 @@ describe('EthGenesisVault', () => { 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) @@ -441,6 +397,33 @@ describe('EthGenesisVault', () => { await snapshotGasCost(receipt) }) + it('skips updating legacy with zero total assets', async () => { + if (MAINNET_FORK.enabled) return + 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/EthPrivErc20Vault.spec.ts b/test/EthPrivErc20Vault.spec.ts index 19b20480..52f4fcac 100644 --- a/test/EthPrivErc20Vault.spec.ts +++ b/test/EthPrivErc20Vault.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 { 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' @@ -18,7 +23,10 @@ describe('EthPrivErc20Vault', () => { const referrer = ZERO_ADDRESS const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' let sender: Wallet, admin: Signer, other: Wallet - let vault: EthPrivErc20Vault, keeper: Keeper, validatorsRegistry: Contract + let vault: EthPrivErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController let createPrivateVault: ThenArg>['createEthPrivErc20Vault'] @@ -28,6 +36,7 @@ describe('EthPrivErc20Vault', () => { createEthPrivErc20Vault: createPrivateVault, keeper, validatorsRegistry, + osTokenVaultController, } = await loadFixture(ethVaultFixture)) vault = await createPrivateVault(admin, { capacity, @@ -44,13 +53,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 +144,68 @@ 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('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 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 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 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 new file mode 100644 index 00000000..746b6c33 --- /dev/null +++ b/test/EthPrivVault.spec.ts @@ -0,0 +1,79 @@ +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 { ethVaultFixture } from './shared/fixtures' +import { expect } from './shared/expect' +import { ZERO_ADDRESS } from './shared/constants' +import snapshotGasCost from './shared/snapshotGasCost' +import { collateralizeEthVault } from './shared/rewards' +import keccak256 from 'keccak256' + +describe('EthPrivVault', () => { + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Signer, other: Wallet + let vault: EthPrivVault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController + + beforeEach('deploy fixtures', async () => { + ;[sender, admin, other] = 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) + }) + }) +}) 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..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.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..0a8fbfe1 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, + deployEthVaultImplementation, + 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 deployEthVaultImplementation( + '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', + const newImpl = await deployEthVaultImplementation( + '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', + const newImpl = await deployEthVaultImplementation( + '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..ed1e1b9a 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, + upgradeVault, +} 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 upgradeVault(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, positionTicket, 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) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(holder.address, receiver.address, positionTicket, holderShares, 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, positionTicketV1, 0n, holderV1Assets) + await expect(vault.connect(holderV2).claimExitedAssets(positionTicketV2, timestampV2, 0n)) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(holderV2.address, positionTicketV2, 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, positionTicket, 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, positionTicketV1, 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, positionTicketV1, 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, positionTicketV1, 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, newPositionTicket, 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) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(alice.address, alice.address, alicePositionTicket, 1000, 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) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(bob.address, bob.address, bobPositionTicket, 4393, 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, 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, alicePositionTicket, 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) + .to.emit(vault, 'V2ExitQueueEntered') + .withArgs(alice.address, alice.address, latestPositionTicket, 1001, 6824) 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, bobPositionTicket, 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, alicePositionTicket, 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/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 new file mode 100644 index 00000000..1180d9c3 --- /dev/null +++ b/test/__snapshots__/EthBlocklistErc20Vault.spec.ts.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EthBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 71181, +} +`; + +exports[`EthBlocklistErc20Vault deposit deposit through receive fallback can be called by not blocked sender 1`] = ` +Object { + "calldataByteLength": 4, + "gasUsed": 78347, +} +`; + +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": 58987, +} +`; diff --git a/test/__snapshots__/EthBlocklistVault.spec.ts.snap b/test/__snapshots__/EthBlocklistVault.spec.ts.snap new file mode 100644 index 00000000..f422fa1e --- /dev/null +++ b/test/__snapshots__/EthBlocklistVault.spec.ts.snap @@ -0,0 +1,22 @@ +// 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 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..e4386f4c 100644 --- a/test/__snapshots__/EthErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthErc20Vault.spec.ts.snap @@ -17,14 +17,7 @@ Object { 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": 96285, } `; diff --git a/test/__snapshots__/EthFoxVault.spec.ts.snap b/test/__snapshots__/EthFoxVault.spec.ts.snap index 14e86469..a4d88765 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": 68968, } `; 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": 112108, -} -`; - -exports[`EthFoxVault ejecting user blocklist manager can eject all of the user assets for not collateralized vault 1`] = ` -Object { - "calldataByteLength": 36, - "gasUsed": 83278, + "gasUsed": 119659, } `; exports[`EthFoxVault ejecting user does not fail for user with no vault shares 1`] = ` Object { "calldataByteLength": 36, - "gasUsed": 55808, + "gasUsed": 55791, } `; 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..26beb1a3 100644 --- a/test/__snapshots__/EthGenesisVault.spec.ts.snap +++ b/test/__snapshots__/EthGenesisVault.spec.ts.snap @@ -10,48 +10,55 @@ Object { exports[`EthGenesisVault migrate migrates from rewardEthToken 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 79671, + "gasUsed": 79660, } `; -exports[`EthGenesisVault pulls assets on claim exited assets 1`] = ` +exports[`EthGenesisVault pulls withdrawals on claim exited assets 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 62296, + "gasUsed": 77278, } `; -exports[`EthGenesisVault pulls assets on multiple validators registration 1`] = ` +exports[`EthGenesisVault pulls withdrawals on multiple validators registration 1`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 636076, + "gasUsed": 638255, } `; -exports[`EthGenesisVault pulls assets on single validator registration 1`] = ` +exports[`EthGenesisVault pulls withdrawals on single validator registration 1`] = ` Object { "calldataByteLength": 1124, - "gasUsed": 299702, + "gasUsed": 301853, } `; exports[`EthGenesisVault update state deducts rewards on first state update 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 150215, + "gasUsed": 150264, +} +`; + +exports[`EthGenesisVault update state skips updating legacy with zero total assets 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 145833, } `; exports[`EthGenesisVault update state splits penalty between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 100296, + "gasUsed": 119650, } `; exports[`EthGenesisVault update state splits reward between rewardEthToken and vault 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 167315, + "gasUsed": 167364, } `; diff --git a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap index de6ccf5f..d005196a 100644 --- a/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap +++ b/test/__snapshots__/EthPrivErc20Vault.spec.ts.snap @@ -3,13 +3,27 @@ exports[`EthPrivErc20Vault deposit can be called by whitelisted user 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 71069, + "gasUsed": 71169, } `; exports[`EthPrivErc20Vault deposit deposit through receive fallback can be called by whitelisted sender 1`] = ` Object { "calldataByteLength": 4, - "gasUsed": 78288, + "gasUsed": 78350, +} +`; + +exports[`EthPrivErc20Vault mint osToken can mint from whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 174096, +} +`; + +exports[`EthPrivErc20Vault transfer can transfer to whitelisted user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 59015, } `; diff --git a/test/__snapshots__/EthPrivVault.spec.ts.snap b/test/__snapshots__/EthPrivVault.spec.ts.snap new file mode 100644 index 00000000..ebdedaf3 --- /dev/null +++ b/test/__snapshots__/EthPrivVault.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +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..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": 207274, + "gasUsed": 155321, } `; 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..cd9430e5 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": 168451, } `; exports[`EthVault - multicall can update state and queue for exit 2`] = ` Object { "calldataByteLength": 548, - "gasUsed": 137505, + "gasUsed": 109844, } `; 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..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": 671554, + "gasUsed": 673669, } `; exports[`EthVault - register single validator succeeds 1`] = ` Object { "calldataByteLength": 1156, - "gasUsed": 322033, + "gasUsed": 324148, } `; diff --git a/test/__snapshots__/EthVault.settings.spec.ts.snap b/test/__snapshots__/EthVault.settings.spec.ts.snap index e7aaef84..35a28b8d 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": 44014, } `; 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..6f1db2a9 100644 --- a/test/__snapshots__/EthVault.state.spec.ts.snap +++ b/test/__snapshots__/EthVault.state.spec.ts.snap @@ -3,14 +3,21 @@ exports[`EthVault - state allocates fee to recipient when delta is above zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 117567, + "gasUsed": 117553, } `; exports[`EthVault - state applies penalty when delta is below zero 1`] = ` Object { "calldataByteLength": 196, - "gasUsed": 115144, + "gasUsed": 117338, +} +`; + +exports[`EthVault - state splits penalty between exiting assets and staking assets 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 107117, } `; diff --git a/test/__snapshots__/EthVault.token.spec.ts.snap b/test/__snapshots__/EthVault.token.spec.ts.snap index 88081c47..29a129bd 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": 82411, + "gasUsed": 82389, } `; @@ -38,13 +38,13 @@ Object { exports[`EthVault - token transfer when the sender transfers all balance transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 54487, + "gasUsed": 54465, } `; exports[`EthVault - token transfer when the sender transfers zero tokens transfers the requested amount 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 36563, + "gasUsed": 36541, } `; 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..9f11d9f4 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": 76025, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in multiple transactions 2`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48012, + "gasUsed": 48843, } `; exports[`EthVault - withdraw claim exited assets for single user in multiple checkpoints in single transaction 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 50422, + "gasUsed": 51461, } `; exports[`EthVault - withdraw claim exited assets for single user in single checkpoint 1`] = ` Object { "calldataByteLength": 100, - "gasUsed": 48012, + "gasUsed": 48843, } `; -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": 77382, } `; diff --git a/test/__snapshots__/EthVaultFactory.spec.ts.snap b/test/__snapshots__/EthVaultFactory.spec.ts.snap index 339c4b4e..406947fa 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": 577199, } `; exports[`EthVaultFactory EthErc20Vault private vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 453346, + "gasUsed": 428380, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with own escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 553968, + "gasUsed": 553267, } `; exports[`EthVaultFactory EthErc20Vault public vault deployment with shared escrow gas 1`] = ` Object { "calldataByteLength": 516, - "gasUsed": 405149, + "gasUsed": 404448, } `; 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__/KeeperRewards.spec.ts.snap b/test/__snapshots__/KeeperRewards.spec.ts.snap index 458c5911..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": 111388, + "gasUsed": 111374, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 324, - "gasUsed": 113542, + "gasUsed": 113528, } `; exports[`KeeperRewards harvest (own escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 74309, + "gasUsed": 74295, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for latest rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 143942, + "gasUsed": 143928, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 1`] = ` Object { "calldataByteLength": 292, - "gasUsed": 146096, + "gasUsed": 146082, } `; exports[`KeeperRewards harvest (shared escrow) succeeds for previous rewards root 2`] = ` Object { "calldataByteLength": 196, - "gasUsed": 90476, + "gasUsed": 90462, } `; diff --git a/test/__snapshots__/KeeperValidators.spec.ts.snap b/test/__snapshots__/KeeperValidators.spec.ts.snap index adbe7f1e..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": 677871, + "gasUsed": 679986, } `; exports[`KeeperValidators register multiple validators succeeds 2`] = ` Object { "calldataByteLength": 3716, - "gasUsed": 586277, + "gasUsed": 588392, } `; exports[`KeeperValidators register single validator succeeds 1`] = ` Object { "calldataByteLength": 1540, - "gasUsed": 328397, + "gasUsed": 330512, } `; exports[`KeeperValidators register single validator succeeds 2`] = ` Object { "calldataByteLength": 1508, - "gasUsed": 274125, + "gasUsed": 276240, } `; diff --git a/test/__snapshots__/RewardSplitter.spec.ts.snap b/test/__snapshots__/RewardSplitter.spec.ts.snap index becc84c9..f2cc9f02 100644 --- a/test/__snapshots__/RewardSplitter.spec.ts.snap +++ b/test/__snapshots__/RewardSplitter.spec.ts.snap @@ -10,7 +10,7 @@ Object { exports[`RewardSplitter increase shares owner can increase shares 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78767, + "gasUsed": 78745, } `; @@ -24,13 +24,13 @@ Object { exports[`RewardSplitter withdraw rewards can claim vault tokens for ERC-20 vault 1`] = ` Object { "calldataByteLength": 68, - "gasUsed": 78224, + "gasUsed": 78180, } `; exports[`RewardSplitter withdraw rewards can enter exit queue with multicall 1`] = ` Object { "calldataByteLength": 612, - "gasUsed": 168565, + "gasUsed": 170884, } `; 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/gnosis/GnoBlocklistErc20Vault.spec.ts b/test/gnosis/GnoBlocklistErc20Vault.spec.ts new file mode 100644 index 00000000..40a50932 --- /dev/null +++ b/test/gnosis/GnoBlocklistErc20Vault.spec.ts @@ -0,0 +1,154 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + ERC20Mock, + GnoBlocklistErc20Vault, + Keeper, + OsTokenVaultController, +} from '../../typechain-types' +import { collateralizeGnoVault, depositGno, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_ADDRESS } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import keccak256 from 'keccak256' +import { extractDepositShares } from '../shared/utils' + +describe('GnoBlocklistErc20Vault', () => { + const name = 'SW GNO Vault' + const symbol = 'SW-GNO-1' + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Wallet, other: Wallet, blocklistManager: Wallet, receiver: Wallet + let vault: GnoBlocklistErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + gnoToken: ERC20Mock + + beforeEach('deploy fixtures', async () => { + ;[sender, receiver, admin, other, blocklistManager] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + vault = await fixture.createGnoBlocklistErc20Vault(admin, { + name, + symbol, + capacity, + feePercent, + metadataIpfsHash, + }) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + gnoToken = fixture.gnoToken + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoBlocklistErc20Vault').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 depositGno(vault, gnoToken, amount, sender, sender, referrer) + }) + + 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 depositGno(vault, gnoToken, amount, other, other, referrer) + 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( + depositGno(vault, gnoToken, assets, other, receiver, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to blocked user', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + depositGno(vault, gnoToken, assets, sender, other, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by not blocked user', async () => { + const receipt = await depositGno(vault, gnoToken, assets, sender, receiver, referrer) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, receiver.address, assets, shares, referrer) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + 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) + }) + }) +}) diff --git a/test/gnosis/GnoBlocklistVault.spec.ts b/test/gnosis/GnoBlocklistVault.spec.ts new file mode 100644 index 00000000..3e080a74 --- /dev/null +++ b/test/gnosis/GnoBlocklistVault.spec.ts @@ -0,0 +1,110 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { ERC20Mock, GnoBlocklistVault, Keeper, OsTokenVaultController } from '../../typechain-types' +import { collateralizeGnoVault, depositGno, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_ADDRESS } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import keccak256 from 'keccak256' +import { extractDepositShares } from '../shared/utils' + +describe('GnoBlocklistVault', () => { + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Wallet, other: Wallet, blocklistManager: Wallet, receiver: Wallet + let vault: GnoBlocklistVault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + gnoToken: ERC20Mock + + beforeEach('deploy fixtures', async () => { + ;[sender, receiver, admin, other, blocklistManager] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + vault = await fixture.createGnoBlocklistVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + gnoToken = fixture.gnoToken + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoBlocklistVault').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( + depositGno(vault, gnoToken, assets, other, receiver, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to blocked user', async () => { + await vault.connect(blocklistManager).updateBlocklist(other.address, true) + await expect( + depositGno(vault, gnoToken, assets, sender, other, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by not blocked user', async () => { + const receipt = await depositGno(vault, gnoToken, assets, sender, receiver, referrer) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, receiver.address, assets, shares, referrer) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + 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) + }) + }) +}) diff --git a/test/gnosis/GnoErc20Vault.spec.ts b/test/gnosis/GnoErc20Vault.spec.ts new file mode 100644 index 00000000..3ef9489e --- /dev/null +++ b/test/gnosis/GnoErc20Vault.spec.ts @@ -0,0 +1,153 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import keccak256 from 'keccak256' +import { ERC20Mock, GnoErc20Vault, Keeper, OsTokenVaultController } from '../../typechain-types' +import { collateralizeGnoVault, depositGno, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_ADDRESS } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import { extractExitPositionTicket } from '../shared/utils' +import { getHarvestParams, updateRewards } from '../shared/rewards' + +describe('GnoErc20Vault', () => { + const name = 'SW GNO Vault' + const symbol = 'SW-GNO-1' + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Wallet, other: Wallet, receiver: Wallet + let vault: GnoErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + gnoToken: ERC20Mock + + beforeEach('deploy fixtures', async () => { + ;[sender, receiver, admin, other] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + vault = await fixture.createGnoErc20Vault(admin, { + name, + symbol, + capacity, + feePercent, + metadataIpfsHash, + }) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + gnoToken = fixture.gnoToken + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoErc20Vault').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' + ) + }) + + it('deposit emits transfer event', async () => { + const amount = ethers.parseEther('100') + const expectedShares = await vault.convertToShares(amount) + const receipt = await depositGno(vault, gnoToken, amount, sender, receiver, referrer) + expect(await vault.balanceOf(receiver.address)).to.eq(expectedShares) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, receiver.address, amount, expectedShares, referrer) + await expect(receipt) + .to.emit(vault, 'Transfer') + .withArgs(ZERO_ADDRESS, receiver.address, expectedShares) + await snapshotGasCost(receipt) + }) + + it('enter exit queue emits transfer event', async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + expect(await vault.totalExitingAssets()).to.be.eq(0) + const totalExitingBefore = await vault.totalExitingAssets() + const totalAssetsBefore = await vault.totalAssets() + const totalSharesBefore = await vault.totalShares() + + const amount = ethers.parseEther('100') + const shares = await vault.convertToShares(amount) + await depositGno(vault, gnoToken, amount, sender, sender, referrer) + expect(await vault.balanceOf(sender.address)).to.be.eq(shares) + + const receipt = await vault.connect(sender).enterExitQueue(shares, receiver.address) + const positionTicket = await extractExitPositionTicket(receipt) + await expect(receipt) + .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) + expect(await vault.totalSupply()).to.be.eq(totalSharesBefore) + expect(await vault.balanceOf(sender.address)).to.be.eq(0) + + await snapshotGasCost(receipt) + }) + + it('cannot transfer vault shares when unharvested and osToken minted', async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + const assets = ethers.parseEther('1') + const shares = await vault.convertToShares(assets) + const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + await vault.connect(sender).mintOsToken(receiver.address, osTokenShares, ZERO_ADDRESS) + + await updateRewards(keeper, [ + getHarvestParams(await vault.getAddress(), ethers.parseEther('1'), ethers.parseEther('0')), + ]) + await updateRewards(keeper, [ + getHarvestParams(await vault.getAddress(), ethers.parseEther('1.2'), ethers.parseEther('0')), + ]) + await expect( + vault.connect(sender).transfer(receiver.address, shares) + ).to.be.revertedWithCustomError(vault, 'NotHarvested') + }) + + it('cannot transfer vault shares when LTV is violated', async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + const assets = ethers.parseEther('2') + const shares = await vault.convertToShares(assets) + const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + await vault.connect(sender).mintOsToken(receiver.address, osTokenShares, ZERO_ADDRESS) + await expect( + vault.connect(sender).transfer(receiver.address, shares) + ).to.be.revertedWithCustomError(vault, 'LowLtv') + await vault.connect(sender).approve(receiver.address, shares) + await expect( + vault.connect(receiver).transferFrom(sender.address, receiver.address, shares) + ).to.be.revertedWithCustomError(vault, 'LowLtv') + }) + + it('can transfer vault shares when LTV is not violated', async () => { + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + const assets = ethers.parseEther('2') + const osTokenShares = await osTokenVaultController.convertToShares(assets / 2n) + const transferShares = await vault.convertToShares(ethers.parseEther('0.1')) + + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + await vault.connect(sender).mintOsToken(receiver.address, osTokenShares, ZERO_ADDRESS) + await expect(vault.connect(sender).transfer(receiver.address, transferShares)).to.emit( + vault, + 'Transfer' + ) + await vault.connect(sender).approve(receiver.address, transferShares) + await expect( + vault.connect(receiver).transferFrom(sender.address, receiver.address, transferShares) + ).to.emit(vault, 'Transfer') + }) +}) diff --git a/test/gnosis/GnoGenesisVault.spec.ts b/test/gnosis/GnoGenesisVault.spec.ts new file mode 100644 index 00000000..8b7e775d --- /dev/null +++ b/test/gnosis/GnoGenesisVault.spec.ts @@ -0,0 +1,419 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + ERC20Mock, + GnoGenesisVault, + Keeper, + LegacyRewardTokenMock, + PoolEscrowMock, +} from '../../typechain-types' +import { expect } from '../shared/expect' +import keccak256 from 'keccak256' +import { + EXITING_ASSETS_MIN_DELAY, + SECURITY_DEPOSIT, + ZERO_ADDRESS, + ZERO_BYTES32, +} from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import { registerEthValidator } from '../shared/validators' +import { getHarvestParams, getRewardsRootProof, updateRewards } from '../shared/rewards' +import { + extractDepositShares, + extractExitPositionTicket, + getBlockTimestamp, + increaseTime, +} from '../shared/utils' +import { ThenArg } from '../../helpers/types' +import { + collateralizeGnoVault, + depositGno, + gnoVaultFixture, + setGnoWithdrawals, +} from '../shared/gnoFixtures' + +describe('GnoGenesisVault', () => { + const capacity = ethers.parseEther('1000000') + const feePercent = 500 + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let admin: Wallet, other: Wallet + let vault: GnoGenesisVault, keeper: Keeper, validatorsRegistry: Contract, gnoToken: ERC20Mock + let poolEscrow: PoolEscrowMock + let rewardToken: LegacyRewardTokenMock + + let createGenesisVault: ThenArg>['createGnoGenesisVault'] + + async function acceptPoolEscrowOwnership() { + await vault.connect(admin).acceptPoolEscrowOwnership() + } + + async function collatGnoVault() { + await collateralizeGnoVault( + vault, + gnoToken, + keeper, + validatorsRegistry, + admin, + await poolEscrow.getAddress() + ) + } + + beforeEach('deploy fixtures', async () => { + ;[admin, other] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + gnoToken = fixture.gnoToken + ;[vault, rewardToken, poolEscrow] = await fixture.createGnoGenesisVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + createGenesisVault = fixture.createGnoGenesisVault + }) + + it('initializes correctly', async () => { + await expect(vault.connect(admin).initialize(ZERO_BYTES32)).to.revertedWithCustomError( + vault, + 'InvalidInitialization' + ) + expect(await vault.capacity()).to.be.eq(capacity) + + // VaultAdmin + const adminAddr = await admin.getAddress() + + // VaultVersion + expect(await vault.version()).to.be.eq(2) + expect(await vault.vaultId()).to.be.eq(`0x${keccak256('GnoGenesisVault').toString('hex')}`) + + // VaultFee + expect(await vault.admin()).to.be.eq(adminAddr) + expect(await vault.feeRecipient()).to.be.eq(adminAddr) + }) + + it('has version', async () => { + expect(await vault.version()).to.eq(2) + }) + + describe('migrate', () => { + it('fails from not rewardToken', async () => { + await expect( + vault.connect(admin).migrate(await admin.getAddress(), ethers.parseEther('1')) + ).to.be.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('fails when pool escrow ownership is not accepted', async () => { + const [vault, rewardToken] = await createGenesisVault( + admin, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + const assets = ethers.parseEther('10') + await expect( + rewardToken.connect(other).migrate(other.address, assets, 0) + ).to.be.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('fails with zero receiver', async () => { + await acceptPoolEscrowOwnership() + await collatGnoVault() + const assets = ethers.parseEther('1') + await expect( + rewardToken.connect(other).migrate(ZERO_ADDRESS, assets, assets) + ).to.be.revertedWithCustomError(vault, 'ZeroAddress') + }) + + it('fails with zero assets', async () => { + await acceptPoolEscrowOwnership() + await collatGnoVault() + await expect( + rewardToken.connect(other).migrate(other.address, 0, 0) + ).to.be.revertedWithCustomError(vault, 'InvalidAssets') + }) + + it('fails when not collateralized', async () => { + const [vault, rewardToken] = await createGenesisVault( + admin, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + await vault.connect(admin).acceptPoolEscrowOwnership() + const assets = ethers.parseEther('1') + await expect( + rewardToken.connect(other).migrate(other.address, assets, assets) + ).to.be.revertedWithCustomError(vault, 'NotCollateralized') + }) + + it('fails when not harvested', async () => { + await acceptPoolEscrowOwnership() + await collatGnoVault() + const reward = ethers.parseEther('5') + const unlockedMevReward = 0n + const vaultAddr = await vault.getAddress() + const vaultReward = getHarvestParams(vaultAddr, reward, unlockedMevReward) + await updateRewards(keeper, [vaultReward]) + await updateRewards(keeper, [ + getHarvestParams(vaultAddr, reward + ethers.parseEther('5'), unlockedMevReward), + ]) + + const holder = other + const assets = ethers.parseEther('1') + await expect( + rewardToken.connect(holder).migrate(await holder.getAddress(), assets, assets) + ).to.be.revertedWithCustomError(vault, 'NotHarvested') + }) + + it('migrates from rewardToken', async () => { + await acceptPoolEscrowOwnership() + await collatGnoVault() + const assets = ethers.parseEther('10') + const expectedShares = await vault.convertToShares(assets) + + const holder = other + const holderAddr = await holder.getAddress() + + const receipt = await rewardToken.connect(holder).migrate(holderAddr, assets, 0) + expect(await vault.getShares(holderAddr)).to.eq(expectedShares) + + await expect(receipt).to.emit(vault, 'Migrated').withArgs(holderAddr, assets, expectedShares) + await snapshotGasCost(receipt) + }) + }) + + it('pulls withdrawals on claim exited assets', async () => { + await acceptPoolEscrowOwnership() + const assets = ethers.parseEther('1') - SECURITY_DEPOSIT + let tx = await depositGno(vault, gnoToken, assets, other, other, ZERO_ADDRESS) + const shares = await extractDepositShares(tx) + expect(await vault.getShares(other.address)).to.eq(shares) + + // register validator + await registerEthValidator( + vault, + keeper, + validatorsRegistry, + admin, + await poolEscrow.getAddress() + ) + expect(await gnoToken.balanceOf(await vault.getAddress())).to.eq(0n) + + // enter exit queue + tx = await vault.connect(other).enterExitQueue(shares, other.address) + const positionTicket = await extractExitPositionTicket(tx) + const timestamp = await getBlockTimestamp(tx) + expect(await vault.getExitQueueIndex(positionTicket)).to.eq(-1) + + // withdrawals arrives + await setGnoWithdrawals(validatorsRegistry, gnoToken, poolEscrow, assets) + const exitQueueIndex = await vault.getExitQueueIndex(positionTicket) + expect(exitQueueIndex).to.eq(0) + expect(await vault.withdrawableAssets()).to.eq(0n) + + // claim exited assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) + tx = await vault.connect(other).claimExitedAssets(positionTicket, timestamp, exitQueueIndex) + await expect(tx) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(other.address, positionTicket, 0, assets) + await snapshotGasCost(tx) + }) + + describe('update state', () => { + let totalVaultAssets: bigint + let totalLegacyAssets: bigint + + beforeEach(async () => { + totalVaultAssets = ethers.parseEther('10') + totalLegacyAssets = ethers.parseEther('5') + await depositGno( + vault, + gnoToken, + totalVaultAssets - SECURITY_DEPOSIT, + other, + other, + ZERO_ADDRESS + ) + await rewardToken.connect(other).setTotalStaked(totalLegacyAssets) + }) + + it('splits reward between rewardToken and vault', async () => { + await acceptPoolEscrowOwnership() + const reward = ethers.parseEther('30') + const unlockedMevReward = 0n + const expectedVaultDelta = + (reward * totalVaultAssets) / (totalLegacyAssets + totalVaultAssets) + const expectedLegacyDelta = reward - expectedVaultDelta + const vaultReward = getHarvestParams(await vault.getAddress(), reward, unlockedMevReward) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + + expect(await rewardToken.totalAssets()).to.eq(totalLegacyAssets + expectedLegacyDelta) + expect(await vault.totalAssets()).to.eq(totalVaultAssets + expectedVaultDelta) + await snapshotGasCost(receipt) + }) + + it('skips updating legacy with zero total assets', async () => { + await acceptPoolEscrowOwnership() + await rewardToken.setTotalStaked(0n) + await rewardToken.setTotalRewards(0n) + await rewardToken.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 rewardToken.totalAssets() + const totalVaultAssetsBefore = await vault.totalAssets() + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + expect(await rewardToken.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, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + const totalRewards = ethers.parseEther('30') + const vaultReward = getHarvestParams(await vault.getAddress(), totalRewards, 0n) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + await expect( + vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + ).to.be.revertedWithCustomError(vault, 'InvalidInitialHarvest') + }) + + it('fails with negative first update', async () => { + const [vault] = await createGenesisVault( + admin, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + await vault.connect(admin).acceptPoolEscrowOwnership() + const totalPenalty = ethers.parseEther('-5') + const vaultReward = getHarvestParams(await vault.getAddress(), totalPenalty, 0n) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + await expect( + vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + ).to.revertedWithCustomError(vault, 'InvalidInitialHarvest') + }) + + it('splits penalty between rewardToken and vault', async () => { + await acceptPoolEscrowOwnership() + await collatGnoVault() + const reward = ethers.parseEther('-5') + const unlockedMevReward = 0n + const expectedVaultDelta = + (reward * totalVaultAssets) / (totalLegacyAssets + totalVaultAssets) + const expectedLegacyDelta = reward - expectedVaultDelta + const vaultReward = getHarvestParams(await vault.getAddress(), reward, unlockedMevReward) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + + expect((await rewardToken.totalAssets()) - (await rewardToken.totalPenalty())).to.eq( + totalLegacyAssets + expectedLegacyDelta + 1n // rounding error + ) + expect(await vault.totalAssets()).to.eq(totalVaultAssets + expectedVaultDelta - 1n) // rounding error + await snapshotGasCost(receipt) + }) + + it('deducts rewards on first state update', async () => { + const [vault, rewardToken] = await createGenesisVault( + admin, + { + capacity, + feePercent, + metadataIpfsHash, + }, + true + ) + await vault.connect(admin).acceptPoolEscrowOwnership() + await depositGno( + vault, + gnoToken, + totalVaultAssets - SECURITY_DEPOSIT, + other, + other, + ZERO_ADDRESS + ) + await rewardToken.connect(other).setTotalStaked(totalLegacyAssets) + + const totalRewards = ethers.parseEther('25') + const legacyRewards = ethers.parseEther('5') + await rewardToken.connect(other).setTotalRewards(legacyRewards) + expect(await rewardToken.totalAssets()).to.eq(totalLegacyAssets + legacyRewards) + expect(await rewardToken.totalRewards()).to.eq(legacyRewards) + expect(await vault.totalAssets()).to.eq(totalVaultAssets) + + const expectedVaultDelta = + ((totalRewards - legacyRewards) * totalVaultAssets) / + (totalLegacyAssets + legacyRewards + totalVaultAssets) + const expectedLegacyDelta = totalRewards - legacyRewards - expectedVaultDelta + const vaultReward = getHarvestParams(await vault.getAddress(), totalRewards, 0n) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + + expect(await rewardToken.totalAssets()).to.eq( + totalLegacyAssets + legacyRewards + expectedLegacyDelta + ) + expect(await vault.totalAssets()).to.eq(totalVaultAssets + expectedVaultDelta) + await snapshotGasCost(receipt) + }) + }) +}) diff --git a/test/gnosis/GnoOwnMevEscrow.spec.ts b/test/gnosis/GnoOwnMevEscrow.spec.ts new file mode 100644 index 00000000..bdab9079 --- /dev/null +++ b/test/gnosis/GnoOwnMevEscrow.spec.ts @@ -0,0 +1,46 @@ +import { ethers } from 'hardhat' +import { ContractFactory, Wallet } from 'ethers' +import { OwnMevEscrow__factory } from '../../typechain-types' +import snapshotGasCost from '../shared/snapshotGasCost' +import { expect } from '../shared/expect' + +describe('GnoOwnMevEscrow', () => { + let ownMevEscrowFactory: ContractFactory + let vault: Wallet, other: Wallet + + before(async () => { + ;[vault, other] = await (ethers as any).getSigners() + ownMevEscrowFactory = await ethers.getContractFactory('GnoOwnMevEscrow') + }) + + it('vault deployment gas', async () => { + const contract = await ownMevEscrowFactory.deploy(await vault.getAddress()) + await snapshotGasCost(contract.deploymentTransaction() as any) + }) + + it('only vault can withdraw assets', async () => { + const tx = await ethers.deployContract('GnoOwnMevEscrow', [await vault.getAddress()]) + const contract = await tx.waitForDeployment() + const ownMevEscrow = OwnMevEscrow__factory.connect(await contract.getAddress(), other) + await expect(ownMevEscrow.connect(other).harvest()).to.be.revertedWithCustomError( + ownMevEscrow, + 'HarvestFailed' + ) + }) + + it('emits event on transfers', async () => { + const value = ethers.parseEther('1') + const tx = await ethers.deployContract('OwnMevEscrow', [await vault.getAddress()]) + const contract = await tx.waitForDeployment() + const ownMevEscrow = OwnMevEscrow__factory.connect(await contract.getAddress(), other) + + await expect( + other.sendTransaction({ + to: await ownMevEscrow.getAddress(), + value: value, + }) + ) + .to.be.emit(ownMevEscrow, 'MevReceived') + .withArgs(value) + }) +}) diff --git a/test/gnosis/GnoPrivErc20Vault.spec.ts b/test/gnosis/GnoPrivErc20Vault.spec.ts new file mode 100644 index 00000000..44a7dfda --- /dev/null +++ b/test/gnosis/GnoPrivErc20Vault.spec.ts @@ -0,0 +1,151 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { ERC20Mock, GnoPrivErc20Vault, Keeper, OsTokenVaultController } from '../../typechain-types' +import { collateralizeGnoVault, depositGno, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_ADDRESS } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import keccak256 from 'keccak256' +import { extractDepositShares } from '../shared/utils' + +describe('GnoPrivErc20Vault', () => { + const name = 'SW GNO Vault' + const symbol = 'SW-GNO-1' + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Wallet, other: Wallet, whitelister: Wallet, receiver: Wallet + let vault: GnoPrivErc20Vault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + gnoToken: ERC20Mock + + beforeEach('deploy fixtures', async () => { + ;[sender, receiver, admin, other, whitelister] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + vault = await fixture.createGnoPrivErc20Vault(admin, { + name, + symbol, + capacity, + feePercent, + metadataIpfsHash, + }) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + gnoToken = fixture.gnoToken + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoPrivErc20Vault').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 amount = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).setWhitelister(whitelister.address) + await vault.connect(whitelister).updateWhitelist(sender.address, true) + }) + + it('cannot be called by not whitelisted sender', async () => { + await expect( + depositGno(vault, gnoToken, amount, receiver, sender, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to not whitelisted user', async () => { + await expect( + depositGno(vault, gnoToken, amount, sender, receiver, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by whitelisted user', async () => { + const receipt = await depositGno(vault, gnoToken, amount, sender, sender, referrer) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, sender.address, amount, shares, referrer) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + await vault.connect(admin).updateWhitelist(sender.address, true) + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + 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('transfer', () => { + const amount = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(sender.address, true) + await depositGno(vault, gnoToken, amount, sender, sender, referrer) + }) + + 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) + }) + }) +}) diff --git a/test/gnosis/GnoPrivVault.spec.ts b/test/gnosis/GnoPrivVault.spec.ts new file mode 100644 index 00000000..ec704b25 --- /dev/null +++ b/test/gnosis/GnoPrivVault.spec.ts @@ -0,0 +1,111 @@ +import { ethers } from 'hardhat' +import { Contract, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { ERC20Mock, GnoPrivVault, Keeper, OsTokenVaultController } from '../../typechain-types' +import { collateralizeGnoVault, depositGno, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_ADDRESS } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' +import keccak256 from 'keccak256' +import { extractDepositShares } from '../shared/utils' + +describe('GnoPrivVault', () => { + const capacity = ethers.parseEther('1000') + const feePercent = 1000 + const referrer = ZERO_ADDRESS + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + let sender: Wallet, admin: Wallet, other: Wallet, whitelister: Wallet, receiver: Wallet + let vault: GnoPrivVault, + keeper: Keeper, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + gnoToken: ERC20Mock + + beforeEach('deploy fixtures', async () => { + ;[sender, receiver, admin, other, whitelister] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + vault = await fixture.createGnoPrivVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + osTokenVaultController = fixture.osTokenVaultController + gnoToken = fixture.gnoToken + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoPrivVault').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 amount = ethers.parseEther('1') + + beforeEach(async () => { + await vault.connect(admin).setWhitelister(whitelister.address) + await vault.connect(whitelister).updateWhitelist(sender.address, true) + }) + + it('cannot be called by not whitelisted sender', async () => { + await expect( + depositGno(vault, gnoToken, amount, receiver, sender, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot set receiver to not whitelisted user', async () => { + await expect( + depositGno(vault, gnoToken, amount, sender, receiver, referrer) + ).to.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be called by whitelisted user', async () => { + const receipt = await depositGno(vault, gnoToken, amount, sender, sender, referrer) + const shares = await extractDepositShares(receipt) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, sender.address, amount, shares, referrer) + await snapshotGasCost(receipt) + }) + }) + + describe('mint osToken', () => { + const assets = ethers.parseEther('1') + let osTokenShares: bigint + + beforeEach(async () => { + await vault.connect(admin).updateWhitelist(await admin.getAddress(), true) + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + await vault.connect(admin).updateWhitelist(sender.address, true) + await depositGno(vault, gnoToken, assets, sender, sender, referrer) + 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) + }) + }) +}) diff --git a/test/gnosis/GnoSharedMevEscrow.spec.ts b/test/gnosis/GnoSharedMevEscrow.spec.ts new file mode 100644 index 00000000..271d083e --- /dev/null +++ b/test/gnosis/GnoSharedMevEscrow.spec.ts @@ -0,0 +1,42 @@ +import { ethers } from 'hardhat' +import { Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { GnoSharedMevEscrow, VaultsRegistry } from '../../typechain-types' +import snapshotGasCost from '../shared/snapshotGasCost' +import { expect } from '../shared/expect' + +import { gnoVaultFixture } from '../shared/gnoFixtures' + +describe('GnoSharedMevEscrow', () => { + let other: Wallet, sharedMevEscrow: GnoSharedMevEscrow, vaultsRegistry: VaultsRegistry + + beforeEach('deploy fixture', async () => { + ;[other] = (await (ethers as any).getSigners()).slice(1, 2) + ;({ sharedMevEscrow, vaultsRegistry } = await loadFixture(gnoVaultFixture)) + }) + + it('vault deployment gas', async () => { + const sharedMevEscrowFactory = await ethers.getContractFactory('GnoSharedMevEscrow') + const tx = await sharedMevEscrowFactory.deploy(await vaultsRegistry.getAddress()) + await snapshotGasCost(tx.deploymentTransaction() as any) + }) + + it('only vault can withdraw assets', async () => { + await expect( + sharedMevEscrow.connect(other).harvest(ethers.parseEther('1')) + ).to.be.revertedWithCustomError(sharedMevEscrow, 'HarvestFailed') + }) + + it('emits event on transfers', async () => { + const value = ethers.parseEther('1') + + await expect( + other.sendTransaction({ + to: await sharedMevEscrow.getAddress(), + value: value, + }) + ) + .to.be.emit(sharedMevEscrow, 'MevReceived') + .withArgs(value) + }) +}) diff --git a/test/gnosis/GnoVault.register.spec.ts b/test/gnosis/GnoVault.register.spec.ts new file mode 100644 index 00000000..5edea884 --- /dev/null +++ b/test/gnosis/GnoVault.register.spec.ts @@ -0,0 +1,503 @@ +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 { ERC20Mock, GnoVault, IKeeperValidators, Keeper } from '../../typechain-types' +import snapshotGasCost from '../shared/snapshotGasCost' +import { expect } from '../shared/expect' +import { toHexString } from '../shared/utils' +import { + appendDepositData, + createEthValidatorsData, + EthValidatorsData, + exitSignatureIpfsHashes, + getEthValidatorsSigningData, + getValidatorProof, + getValidatorsMultiProof, + getWithdrawalCredentials, + registerEthValidator, + ValidatorsMultiProof, +} from '../shared/validators' +import { getOraclesSignatures } from '../shared/fixtures' +import { + MAX_UINT256, + PANIC_CODES, + SECURITY_DEPOSIT, + VALIDATORS_DEADLINE, + VALIDATORS_MIN_ORACLES, + ZERO_ADDRESS, +} from '../shared/constants' +import { gnoVaultFixture, setGnoWithdrawals } from '../shared/gnoFixtures' + +const gwei = 1000000000n +const uintSerializer = new UintNumberType(8) + +describe('GnoVault - register', () => { + const vaultDeposit = ethers.parseEther('1') + const validatorDeposit = ethers.parseEther('32') + const capacity = MAX_UINT256 + const feePercent = 1000 + const metadataIpfsHash = 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u' + const deadline = VALIDATORS_DEADLINE + + let admin: Signer, other: Wallet + let vault: GnoVault, keeper: Keeper, validatorsRegistry: Contract, gnoToken: ERC20Mock + let validatorsData: EthValidatorsData + let validatorsRegistryRoot: string + + let createVault: ThenArg>['createGnoVault'] + + before('create fixture loader', async () => { + ;[admin, other] = (await (ethers as any).getSigners()).slice(1, 3) + }) + + beforeEach('deploy fixture', async () => { + ;({ + validatorsRegistry, + createGnoVault: createVault, + keeper, + gnoToken, + } = await loadFixture(gnoVaultFixture)) + + vault = await createVault(admin, { + capacity, + feePercent, + metadataIpfsHash, + }) + validatorsData = await createEthValidatorsData(vault) + validatorsRegistryRoot = await validatorsRegistry.get_deposit_root() + await gnoToken.mint(other.address, vaultDeposit) + await gnoToken.connect(other).approve(await vault.getAddress(), vaultDeposit) + await vault.connect(other).deposit(vaultDeposit, other.address, ZERO_ADDRESS) + await vault.connect(admin).setValidatorsRoot(validatorsData.root) + }) + + 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( + validator, + deadline, + exitSignaturesIpfsHash, + keeper, + vault, + validatorsRegistryRoot + ), + VALIDATORS_MIN_ORACLES + ) + approvalParams = { + validatorsRegistryRoot, + validators: validator, + signatures, + exitSignaturesIpfsHash, + deadline, + } + }) + + it('fails with not enough withdrawable assets', async () => { + await vault.connect(other).enterExitQueue(await vault.getShares(other.address), other.address) + await expect(vault.registerValidator(approvalParams, proof)).to.be.revertedWithCustomError( + vault, + 'InsufficientAssets' + ) + }) + + it('fails with invalid proof', async () => { + const invalidProof = getValidatorProof(validatorsData.tree, validatorsData.validators[1], 1) + await expect( + vault.registerValidator(approvalParams, invalidProof) + ).to.be.revertedWithCustomError(vault, 'InvalidProof') + }) + + it('fails with invalid validator length', async () => { + const invalidValidator = appendDepositData( + validator, + 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 + ), + exitSignaturesIpfsHash, + }, + proof + ) + ).to.be.revertedWithCustomError(vault, 'InvalidValidator') + }) + + it('pulls withdrawals on single validator registration', async () => { + await vault.connect(other).enterExitQueue(await vault.getShares(other), other.address) + expect(await vault.withdrawableAssets()).to.eq(SECURITY_DEPOSIT) + await setGnoWithdrawals(validatorsRegistry, gnoToken, vault, vaultDeposit) + expect(await vault.withdrawableAssets()).to.be.eq(vaultDeposit + SECURITY_DEPOSIT) + + const tx = await registerEthValidator(vault, keeper, validatorsRegistry, admin) + await snapshotGasCost(tx) + }) + + it('succeeds', async () => { + const index = await validatorsRegistry.get_deposit_count() + const receipt = await vault.registerValidator(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 + ) + 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]) + indexes = validators.map((v) => sortedVals.indexOf(v)) + + // add gno to vault + const missingGno = vaultDeposit * (BigInt(validators.length) - 1n) + await gnoToken.mint(other.address, missingGno) + await gnoToken.connect(other).approve(await vault.getAddress(), missingGno) + await vault.connect(other).deposit(missingGno, other.address, ZERO_ADDRESS) + await vault.connect(admin).setValidatorsRoot(validatorsData.root) + + 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 with not enough withdrawable assets', async () => { + await vault.connect(other).enterExitQueue(vaultDeposit, other.address) + await expect( + vault.registerValidators(approvalParams, indexes, multiProof.proofFlags, multiProof.proof) + ).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 + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(vault, 'InvalidValidators') + }) + + it('fails with invalid deposit data root', async () => { + const invalidRoot = appendDepositData( + validators[1].subarray(0, 144), + validatorDeposit, + await vault.getAddress() + ).subarray(144, 176) + const invalidValidators = [ + Buffer.concat([validators[0].subarray(0, 144), invalidRoot]), + ...validators.slice(1), + ] + 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 + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWith( + 'DepositContract: reconstructed DepositData does not match supplied deposit_data_root' + ) + }) + + it('fails with invalid deposit amount', async () => { + const invalidValidators = [ + appendDepositData( + validators[0].subarray(0, 144), + ethers.parseEther('1'), + await vault.getAddress() + ), + ...validators.slice(1), + ] + 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 + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWith( + 'DepositContract: reconstructed DepositData does not match supplied deposit_data_root' + ) + }) + + it('fails with invalid withdrawal credentials', async () => { + const invalidValidators = [ + appendDepositData( + validators[0].subarray(0, 144), + ethers.parseEther('1'), + await keeper.getAddress() + ), + ...validators.slice(1), + ] + 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 + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).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), + Buffer.concat([validators[0], validators[1].subarray(0, 10)]), + ] + const exitSignaturesIpfsHash = exitSignatureIpfsHashes[0] + + 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 + ), + exitSignaturesIpfsHash, + }, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + ).to.be.revertedWithCustomError(vault, 'InvalidValidators') + } + }) + + it('pulls withdrawals on multiple validators registration', async () => { + await vault.connect(other).enterExitQueue(await vault.getShares(other), other.address) + expect(await vault.withdrawableAssets()).to.eq(SECURITY_DEPOSIT) + const withdrawals = vaultDeposit * BigInt(validators.length) + await setGnoWithdrawals(validatorsRegistry, gnoToken, vault, withdrawals) + expect(await vault.withdrawableAssets()).to.be.eq(withdrawals + SECURITY_DEPOSIT) + + const tx = await vault.registerValidators( + approvalParams, + indexes, + multiProof.proofFlags, + multiProof.proof + ) + await snapshotGasCost(tx) + }) + + it('succeeds', async () => { + const startIndex = uintSerializer.deserialize( + ethers.getBytes(await validatorsRegistry.get_deposit_count()) + ) + const receipt = await vault.registerValidators( + 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))) + ) + } + await snapshotGasCost(receipt) + }) + }) +}) diff --git a/test/gnosis/GnoVault.spec.ts b/test/gnosis/GnoVault.spec.ts new file mode 100644 index 00000000..4af2bd7f --- /dev/null +++ b/test/gnosis/GnoVault.spec.ts @@ -0,0 +1,233 @@ +import { ethers } from 'hardhat' +import { Contract, parseEther, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + BalancerVaultMock, + ERC20Mock, + GnoVault, + Keeper, + VaultsRegistry, + XdaiExchange, +} from '../../typechain-types' +import { gnoVaultFixture, setGnoWithdrawals } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import snapshotGasCost from '../shared/snapshotGasCost' +import { + extractExitPositionTicket, + getBlockTimestamp, + getLatestBlockTimestamp, + increaseTime, +} from '../shared/utils' +import { + EXITING_ASSETS_MIN_DELAY, + ONE_DAY, + SECURITY_DEPOSIT, + ZERO_ADDRESS, + ZERO_BYTES32, +} from '../shared/constants' +import { registerEthValidator } from '../shared/validators' +import keccak256 from 'keccak256' + +describe('GnoVault', () => { + const vaultParams = { + capacity: ethers.parseEther('1000'), + feePercent: 1000, + metadataIpfsHash: 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u', + } + let dao: Wallet, + other: Wallet, + admin: Wallet, + xdaiManager: Wallet, + sender: Wallet, + receiver: Wallet + let xdaiExchange: XdaiExchange, + gnoToken: ERC20Mock, + balancerVault: BalancerVaultMock, + vault: GnoVault, + vaultsRegistry: VaultsRegistry, + keeper: Keeper, + validatorsRegistry: Contract + + beforeEach('deploy fixtures', async () => { + ;[dao, admin, xdaiManager, sender, receiver, other] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + xdaiExchange = fixture.xdaiExchange + gnoToken = fixture.gnoToken + balancerVault = fixture.balancerVault + vaultsRegistry = fixture.vaultsRegistry + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + vault = await fixture.createGnoVault(admin, vaultParams) + }) + + it('has id', async () => { + expect(await vault.vaultId()).to.eq(`0x${keccak256('GnoVault').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('xdai manager', () => { + it('initially is set to the admin', async () => { + expect(await vault.xdaiManager()).to.eq(admin.address) + }) + + it('cannot be set by non-admin', async () => { + await expect( + vault.connect(other).setXdaiManager(other.address) + ).to.be.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('can be set by the admin', async () => { + const tx = await vault.connect(admin).setXdaiManager(other.address) + expect(await vault.xdaiManager()).to.eq(other.address) + await expect(tx).to.emit(vault, 'XdaiManagerUpdated').withArgs(admin.address, other.address) + await snapshotGasCost(tx) + }) + }) + + describe('swap xdai to gno', () => { + const maxXdaiSwap = ethers.parseEther('12000') + let maxGnoSwap: bigint + let xdaiGnoRate: bigint + let deadline: number + + beforeEach(async () => { + xdaiGnoRate = await balancerVault.xdaiGnoRate() + maxGnoSwap = (maxXdaiSwap * xdaiGnoRate) / parseEther('1') + await gnoToken.mint(await balancerVault.getAddress(), maxGnoSwap) + await other.sendTransaction({ + to: await vault.getAddress(), + value: maxXdaiSwap, + }) + await vault.connect(admin).setXdaiManager(xdaiManager.address) + deadline = (await getLatestBlockTimestamp()) + ONE_DAY + }) + + it('cannot be called by non-xdai manager', async () => { + await expect( + vault.connect(other).swapXdaiToGno(maxXdaiSwap, maxGnoSwap, deadline) + ).to.be.revertedWithCustomError(vault, 'AccessDenied') + }) + + it('cannot swap when below limit', async () => { + const factory = await ethers.getContractFactory('XdaiExchangeV2Mock') + const contract = await factory.deploy( + await gnoToken.getAddress(), + ZERO_BYTES32, + await balancerVault.getAddress(), + await vaultsRegistry.getAddress() + ) + await xdaiExchange.connect(dao).upgradeToAndCall(await contract.getAddress(), '0x') + await expect( + vault.connect(xdaiManager).swapXdaiToGno(maxXdaiSwap, maxGnoSwap, deadline) + ).to.be.revertedWithCustomError(vault, 'InvalidAssets') + }) + + it('manager can swap some xdai to gno', async () => { + const xdaiAmount = maxXdaiSwap / 2n + const gnoAmount = (xdaiAmount * xdaiGnoRate) / parseEther('1') + const totalAssetsBefore = await vault.totalAssets() + const tx = await vault.connect(xdaiManager).swapXdaiToGno(xdaiAmount, gnoAmount, deadline) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + gnoAmount) + await expect(tx).to.emit(vault, 'XdaiSwapped').withArgs(xdaiAmount, gnoAmount) + await snapshotGasCost(tx) + }) + + it('manager can swap all xdai to gno', async () => { + const xdaiAmount = maxXdaiSwap + const gnoAmount = maxGnoSwap + const totalAssetsBefore = await vault.totalAssets() + const tx = await vault.connect(xdaiManager).swapXdaiToGno(xdaiAmount, gnoAmount, deadline) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + gnoAmount) + await expect(tx).to.emit(vault, 'XdaiSwapped').withArgs(xdaiAmount, gnoAmount) + await snapshotGasCost(tx) + }) + }) + + describe('deposit', () => { + const referrer = '0x' + '1'.repeat(40) + const amount = ethers.parseEther('100') + + beforeEach(async () => { + await gnoToken.mint(sender.address, amount) + await gnoToken.connect(sender).approve(await vault.getAddress(), amount) + }) + + it('fails with zero amount', async () => { + await expect( + vault.connect(sender).deposit(0, receiver.address, referrer) + ).to.be.revertedWithCustomError(vault, 'InvalidAssets') + }) + + it('fails with insufficient gno', async () => { + await gnoToken.connect(sender).approve(await vault.getAddress(), amount + 1n) + await expect( + vault.connect(sender).deposit(amount + 1n, receiver.address, referrer) + ).to.be.revertedWithCustomError(gnoToken, 'ERC20InsufficientBalance') + }) + + it('fails with not approved gno', async () => { + await gnoToken.connect(sender).approve(await vault.getAddress(), 0n) + await expect( + vault.connect(sender).deposit(amount, receiver.address, referrer) + ).to.be.revertedWithCustomError(gnoToken, 'ERC20InsufficientAllowance') + }) + + it('deposit', async () => { + const amount = ethers.parseEther('100') + const expectedShares = ethers.parseEther('100') + expect(await vault.convertToShares(amount)).to.eq(expectedShares) + + const receipt = await vault.connect(sender).deposit(amount, receiver.address, referrer) + expect(await vault.getShares(receiver.address)).to.eq(expectedShares) + + await expect(receipt) + .to.emit(vault, 'Deposited') + .withArgs(sender.address, receiver.address, amount, expectedShares, referrer) + await snapshotGasCost(receipt) + }) + }) + + it('pulls withdrawals on claim exited assets', async () => { + // deposit + const assets = ethers.parseEther('1') - SECURITY_DEPOSIT + const shares = await vault.convertToShares(assets) + await gnoToken.mint(sender.address, assets) + await gnoToken.connect(sender).approve(await vault.getAddress(), assets) + await vault.connect(sender).deposit(assets, sender.address, ZERO_ADDRESS) + expect(await vault.getShares(sender.address)).to.eq(shares) + + // register validator + await registerEthValidator(vault, keeper, validatorsRegistry, admin) + expect(await gnoToken.balanceOf(await vault.getAddress())).to.eq(0n) + + // enter exit queue + let tx = await vault.connect(sender).enterExitQueue(shares, receiver.address) + const positionTicket = await extractExitPositionTicket(tx) + const timestamp = await getBlockTimestamp(tx) + expect(await vault.getExitQueueIndex(positionTicket)).to.eq(-1) + + // withdrawals arrives + await setGnoWithdrawals(validatorsRegistry, gnoToken, vault, assets) + const exitQueueIndex = await vault.getExitQueueIndex(positionTicket) + expect(exitQueueIndex).to.eq(0) + expect(await vault.withdrawableAssets()).to.eq(0n) + + // claim exited assets + await increaseTime(EXITING_ASSETS_MIN_DELAY) + tx = await vault.connect(receiver).claimExitedAssets(positionTicket, timestamp, exitQueueIndex) + await expect(tx) + .to.emit(vault, 'ExitedAssetsClaimed') + .withArgs(receiver.address, positionTicket, 0, assets) + await snapshotGasCost(tx) + }) +}) diff --git a/test/gnosis/GnoVault.state.spec.ts b/test/gnosis/GnoVault.state.spec.ts new file mode 100644 index 00000000..d0c01aed --- /dev/null +++ b/test/gnosis/GnoVault.state.spec.ts @@ -0,0 +1,139 @@ +import { ethers } from 'hardhat' +import { Contract, parseEther, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + BalancerVaultMock, + ERC20Mock, + GnoOwnMevEscrow, + GnoOwnMevEscrow__factory, + GnoSharedMevEscrow, + GnoVault, + Keeper, +} from '../../typechain-types' +import { collateralizeGnoVault, gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ThenArg } from '../../helpers/types' +import { getHarvestParams, getRewardsRootProof, updateRewards } from '../shared/rewards' +import { getLatestBlockTimestamp, setBalance } from '../shared/utils' +import snapshotGasCost from '../shared/snapshotGasCost' +import { ONE_DAY } from '../shared/constants' + +describe('GnoVault', () => { + const vaultParams = { + capacity: ethers.parseEther('1000'), + feePercent: 1000, + metadataIpfsHash: 'bafkreidivzimqfqtoqxkrpge6bjyhlvxqs3rhe73owtmdulaxr5do5in7u', + } + let admin: Wallet, xdaiManager: Wallet + let gnoToken: ERC20Mock, + balancerVault: BalancerVaultMock, + sharedMevEscrow: GnoSharedMevEscrow, + keeper: Keeper, + validatorsRegistry: Contract + let xdaiGnoRate: bigint + + let createVault: ThenArg>['createGnoVault'] + + beforeEach('deploy fixtures', async () => { + ;[admin, xdaiManager] = (await (ethers as any).getSigners()).slice(1, 3) + const fixture = await loadFixture(gnoVaultFixture) + gnoToken = fixture.gnoToken + balancerVault = fixture.balancerVault + keeper = fixture.keeper + validatorsRegistry = fixture.validatorsRegistry + sharedMevEscrow = fixture.sharedMevEscrow + createVault = fixture.createGnoVault + }) + + describe('Shared MEV Escrow', () => { + let vault: GnoVault + + beforeEach('deploy vault', async () => { + vault = await createVault(admin, vaultParams, false) + await vault.connect(admin).setXdaiManager(xdaiManager.address) + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + xdaiGnoRate = await balancerVault.xdaiGnoRate() + }) + + it('does not include MEV rewards in total assets delta', async () => { + const vaultAddr = await vault.getAddress() + const consensusReward = parseEther('0.001') + const executionReward = parseEther('0.002') + const vaultReward = getHarvestParams( + await vault.getAddress(), + consensusReward, + executionReward + ) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + await setBalance(await sharedMevEscrow.getAddress(), executionReward) + + const totalAssetsBefore = await vault.totalAssets() + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(0n) + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + consensusReward) + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(executionReward) + expect(receipt).to.emit(sharedMevEscrow, 'Harvested').withArgs(vaultAddr, executionReward) + await snapshotGasCost(receipt) + + const swappedGno = (executionReward * xdaiGnoRate) / parseEther('1') + const deadline = (await getLatestBlockTimestamp()) + ONE_DAY + await gnoToken.mint(await balancerVault.getAddress(), swappedGno) + + await vault.connect(xdaiManager).swapXdaiToGno(executionReward, swappedGno, deadline) + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(0n) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + consensusReward + swappedGno) + }) + }) + + describe('Own MEV Escrow', () => { + let vault: GnoVault + let mevEscrow: GnoOwnMevEscrow + + beforeEach('deploy vault', async () => { + vault = await createVault(admin, vaultParams, true) + const mevEscrowAddr = await vault.mevEscrow() + mevEscrow = GnoOwnMevEscrow__factory.connect(mevEscrowAddr, admin) + await vault.connect(admin).setXdaiManager(xdaiManager.address) + await collateralizeGnoVault(vault, gnoToken, keeper, validatorsRegistry, admin) + xdaiGnoRate = await balancerVault.xdaiGnoRate() + }) + + it('does not include MEV rewards in total assets delta', async () => { + const vaultAddr = await vault.getAddress() + const consensusReward = parseEther('0.001') + const executionReward = parseEther('0.002') + const vaultReward = getHarvestParams(await vault.getAddress(), consensusReward, 0n) + const rewardsTree = await updateRewards(keeper, [vaultReward]) + const proof = getRewardsRootProof(rewardsTree, vaultReward) + await setBalance(await mevEscrow.getAddress(), executionReward) + + const totalAssetsBefore = await vault.totalAssets() + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(0n) + const receipt = await vault.updateState({ + rewardsRoot: rewardsTree.root, + reward: vaultReward.reward, + unlockedMevReward: vaultReward.unlockedMevReward, + proof, + }) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + consensusReward) + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(executionReward) + + expect(receipt).to.emit(mevEscrow, 'Harvested').withArgs(vaultAddr, executionReward) + await snapshotGasCost(receipt) + + const swappedGno = (executionReward * xdaiGnoRate) / parseEther('1') + const deadline = (await getLatestBlockTimestamp()) + ONE_DAY + await gnoToken.mint(await balancerVault.getAddress(), swappedGno) + + await vault.connect(xdaiManager).swapXdaiToGno(executionReward, swappedGno, deadline) + expect(await ethers.provider.getBalance(vaultAddr)).to.eq(0n) + expect(await vault.totalAssets()).to.eq(totalAssetsBefore + consensusReward + swappedGno) + }) + }) +}) diff --git a/test/gnosis/XdaiExchange.spec.ts b/test/gnosis/XdaiExchange.spec.ts new file mode 100644 index 00000000..08650b9a --- /dev/null +++ b/test/gnosis/XdaiExchange.spec.ts @@ -0,0 +1,83 @@ +import { ethers } from 'hardhat' +import { parseEther, Wallet } from 'ethers' +import { loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers' +import { + XdaiExchange, + ERC20Mock, + BalancerVaultMock, + XdaiExchangeV2Mock, + XdaiExchangeV2Mock__factory, + VaultsRegistry, +} from '../../typechain-types' +import { gnoVaultFixture } from '../shared/gnoFixtures' +import { expect } from '../shared/expect' +import { ZERO_BYTES32 } from '../shared/constants' +import snapshotGasCost from '../shared/snapshotGasCost' + +describe('XdaiExchange', () => { + let dao: Wallet, other: Wallet + let xdaiExchange: XdaiExchange, + gnoToken: ERC20Mock, + balancerVault: BalancerVaultMock, + vaultsRegistry: VaultsRegistry + + beforeEach('deploy fixtures', async () => { + ;[dao, other] = await (ethers as any).getSigners() + const fixture = await loadFixture(gnoVaultFixture) + xdaiExchange = fixture.xdaiExchange + gnoToken = fixture.gnoToken + balancerVault = fixture.balancerVault + vaultsRegistry = fixture.vaultsRegistry + }) + + it('cannot initialize twice', async () => { + await expect( + xdaiExchange.connect(other).initialize(other.address) + ).to.be.revertedWithCustomError(xdaiExchange, 'InvalidInitialization') + expect(await xdaiExchange.owner()).to.eq(dao.address) + }) + + describe('upgrade', () => { + let newImpl: XdaiExchangeV2Mock + + beforeEach('deploy new implementation', async () => { + const factory = await ethers.getContractFactory('XdaiExchangeV2Mock') + const contract = await factory.deploy( + await gnoToken.getAddress(), + ZERO_BYTES32, + await balancerVault.getAddress(), + await vaultsRegistry.getAddress() + ) + newImpl = XdaiExchangeV2Mock__factory.connect(await contract.getAddress(), dao) + }) + + it('fails to upgrade if not admin', async () => { + await expect( + xdaiExchange.connect(other).upgradeToAndCall(await newImpl.getAddress(), '0x') + ).revertedWithCustomError(xdaiExchange, 'OwnableUnauthorizedAccount') + }) + + it('upgrades', async () => { + const tx = await xdaiExchange.connect(dao).upgradeToAndCall(await newImpl.getAddress(), '0x') + await expect(tx).to.emit(xdaiExchange, 'Upgraded') + await snapshotGasCost(tx) + }) + }) + + describe('swap', () => { + it('fails for not vault', async () => { + await expect( + xdaiExchange.connect(other).swap(1, 1, { + value: parseEther('1'), + }) + ).to.be.revertedWithCustomError(xdaiExchange, 'AccessDenied') + }) + + it('fails with zero amount', async () => { + await expect(xdaiExchange.connect(dao).swap(1, 1)).to.be.revertedWithCustomError( + xdaiExchange, + 'InvalidAssets' + ) + }) + }) +}) diff --git a/test/gnosis/__snapshots__/GnoBlocklistErc20Vault.spec.ts.snap b/test/gnosis/__snapshots__/GnoBlocklistErc20Vault.spec.ts.snap new file mode 100644 index 00000000..6ba685c7 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoBlocklistErc20Vault.spec.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoBlocklistErc20Vault deposit can be called by not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 86543, +} +`; + +exports[`GnoBlocklistErc20Vault mint osToken can mint from not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 174049, +} +`; + +exports[`GnoBlocklistErc20Vault transfer can transfer 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 59043, +} +`; diff --git a/test/gnosis/__snapshots__/GnoBlocklistVault.spec.ts.snap b/test/gnosis/__snapshots__/GnoBlocklistVault.spec.ts.snap new file mode 100644 index 00000000..54baea35 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoBlocklistVault.spec.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoBlocklistVault deposit can be called by not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 84627, +} +`; + +exports[`GnoBlocklistVault mint osToken can mint from not blocked user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 173839, +} +`; diff --git a/test/gnosis/__snapshots__/GnoErc20Vault.spec.ts.snap b/test/gnosis/__snapshots__/GnoErc20Vault.spec.ts.snap new file mode 100644 index 00000000..96b83019 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoErc20Vault.spec.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoErc20Vault deposit emits transfer event 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 82070, +} +`; + +exports[`GnoErc20Vault enter exit queue emits transfer event 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 96341, +} +`; diff --git a/test/gnosis/__snapshots__/GnoGenesisVault.spec.ts.snap b/test/gnosis/__snapshots__/GnoGenesisVault.spec.ts.snap new file mode 100644 index 00000000..0acef5ae --- /dev/null +++ b/test/gnosis/__snapshots__/GnoGenesisVault.spec.ts.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoGenesisVault migrate migrates from rewardToken 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 79703, +} +`; + +exports[`GnoGenesisVault pulls withdrawals on claim exited assets 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 152032, +} +`; + +exports[`GnoGenesisVault update state deducts rewards on first state update 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 148027, +} +`; + +exports[`GnoGenesisVault update state skips updating legacy with zero total assets 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 143596, +} +`; + +exports[`GnoGenesisVault update state splits penalty between rewardToken and vault 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 117402, +} +`; + +exports[`GnoGenesisVault update state splits reward between rewardToken and vault 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 165127, +} +`; diff --git a/test/gnosis/__snapshots__/GnoOwnMevEscrow.spec.ts.snap b/test/gnosis/__snapshots__/GnoOwnMevEscrow.spec.ts.snap new file mode 100644 index 00000000..83e41998 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoOwnMevEscrow.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoOwnMevEscrow vault deployment gas 1`] = ` +Object { + "calldataByteLength": 719, + "gasUsed": 173636, +} +`; diff --git a/test/gnosis/__snapshots__/GnoPrivErc20Vault.spec.ts.snap b/test/gnosis/__snapshots__/GnoPrivErc20Vault.spec.ts.snap new file mode 100644 index 00000000..cd27716e --- /dev/null +++ b/test/gnosis/__snapshots__/GnoPrivErc20Vault.spec.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoPrivErc20Vault deposit can be called by whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 84571, +} +`; + +exports[`GnoPrivErc20Vault mint osToken can mint from not whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 174074, +} +`; + +exports[`GnoPrivErc20Vault transfer can transfer to whitelisted user 1`] = ` +Object { + "calldataByteLength": 68, + "gasUsed": 59071, +} +`; diff --git a/test/gnosis/__snapshots__/GnoPrivVault.spec.ts.snap b/test/gnosis/__snapshots__/GnoPrivVault.spec.ts.snap new file mode 100644 index 00000000..f8ecd6f0 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoPrivVault.spec.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoPrivVault deposit can be called by whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 82655, +} +`; + +exports[`GnoPrivVault mint osToken can mint from not whitelisted user 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 173864, +} +`; diff --git a/test/gnosis/__snapshots__/GnoSharedMevEscrow.spec.ts.snap b/test/gnosis/__snapshots__/GnoSharedMevEscrow.spec.ts.snap new file mode 100644 index 00000000..0c6ecffa --- /dev/null +++ b/test/gnosis/__snapshots__/GnoSharedMevEscrow.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoSharedMevEscrow vault deployment gas 1`] = ` +Object { + "calldataByteLength": 728, + "gasUsed": 177185, +} +`; diff --git a/test/gnosis/__snapshots__/GnoVault.register.spec.ts.snap b/test/gnosis/__snapshots__/GnoVault.register.spec.ts.snap new file mode 100644 index 00000000..0fba528e --- /dev/null +++ b/test/gnosis/__snapshots__/GnoVault.register.spec.ts.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoVault - register multiple validators pulls withdrawals on multiple validators registration 1`] = ` +Object { + "calldataByteLength": 3332, + "gasUsed": 687987, +} +`; + +exports[`GnoVault - register multiple validators succeeds 1`] = ` +Object { + "calldataByteLength": 3332, + "gasUsed": 708183, +} +`; + +exports[`GnoVault - register single validator pulls withdrawals on single validator registration 1`] = ` +Object { + "calldataByteLength": 1156, + "gasUsed": 350558, +} +`; + +exports[`GnoVault - register single validator succeeds 1`] = ` +Object { + "calldataByteLength": 1156, + "gasUsed": 370754, +} +`; diff --git a/test/gnosis/__snapshots__/GnoVault.spec.ts.snap b/test/gnosis/__snapshots__/GnoVault.spec.ts.snap new file mode 100644 index 00000000..b22288f4 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoVault.spec.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoVault deposit deposit 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 80394, +} +`; + +exports[`GnoVault pulls withdrawals on claim exited assets 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 124820, +} +`; + +exports[`GnoVault swap xdai to gno manager can swap all xdai to gno 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 119517, +} +`; + +exports[`GnoVault swap xdai to gno manager can swap some xdai to gno 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 124305, +} +`; + +exports[`GnoVault xdai manager can be set by the admin 1`] = ` +Object { + "calldataByteLength": 36, + "gasUsed": 52684, +} +`; diff --git a/test/gnosis/__snapshots__/GnoVault.state.spec.ts.snap b/test/gnosis/__snapshots__/GnoVault.state.spec.ts.snap new file mode 100644 index 00000000..3c3d09c7 --- /dev/null +++ b/test/gnosis/__snapshots__/GnoVault.state.spec.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GnoVault Own MEV Escrow does not include MEV rewards in total assets delta 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 99602, +} +`; + +exports[`GnoVault Shared MEV Escrow does not include MEV rewards in total assets delta 1`] = ` +Object { + "calldataByteLength": 196, + "gasUsed": 123790, +} +`; diff --git a/test/gnosis/__snapshots__/XdaiExchange.spec.ts.snap b/test/gnosis/__snapshots__/XdaiExchange.spec.ts.snap new file mode 100644 index 00000000..65e1e793 --- /dev/null +++ b/test/gnosis/__snapshots__/XdaiExchange.spec.ts.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`XdaiExchange upgrade upgrades 1`] = ` +Object { + "calldataByteLength": 100, + "gasUsed": 36983, +} +`; 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/artifacts/GnoValidatorsRegistry.json b/test/shared/artifacts/GnoValidatorsRegistry.json new file mode 100644 index 00000000..e3d8713b --- /dev/null +++ b/test/shared/artifacts/GnoValidatorsRegistry.json @@ -0,0 +1,395 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "pubkeys", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "withdrawal_credentials", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "deposit_data_roots", + "type": "bytes32[]" + } + ], + "name": "batchDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "claimTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "claimWithdrawal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_addresses", + "type": "address[]" + } + ], + "name": "claimWithdrawals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "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" + }, + { + "internalType": "uint256", + "name": "stake_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64[]", + "name": "_amounts", + "type": "uint64[]" + }, + { + "internalType": "address[]", + "name": "_addresses", + "type": "address[]" + } + ], + "name": "executeSystemWithdrawals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint64[]", + "name": "_amounts", + "type": "uint64[]" + }, + { + "internalType": "address[]", + "name": "_addresses", + "type": "address[]" + } + ], + "name": "executeSystemWithdrawals", + "outputs": [], + "stateMutability": "nonpayable", + "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": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "stake_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stake_token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IUnwrapper", + "name": "_unwrapper", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + } + ], + "name": "unwrapTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "validator_withdrawal_credentials", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "withdrawableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a06040523480156200001157600080fd5b506040516200379838038062003798833981016040819052620000349162000050565b6000805460ff191690556001600160a01b031660805262000082565b6000602082840312156200006357600080fd5b81516001600160a01b03811681146200007b57600080fd5b9392505050565b6080516136d0620000c86000396000818161020401528181610415015281816105d80152818161078101528181610b2f01528181610b78015261158d01526136d06000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806369ffa08a116100b2578063a4c0ed3611610081578063be7ab51b11610066578063be7ab51b146102b2578063c5f2892f146102d2578063c82655b7146102da57600080fd5b8063a4c0ed361461028c578063bb30b8fd1461029f57600080fd5b806369ffa08a1461024b57806379d0c0bc1461025e5780638456cb5914610271578063a3066aab1461027957600080fd5b80633f4ba83a116101095780635c975abb116100ee5780635c975abb146101df578063621fd130146101ea578063640415bf146101ff57600080fd5b80633f4ba83a146101c45780634694bd1e146101cc57600080fd5b806301ffc9a71461013b5780630cac9f311461016357806324db4c4614610178578063319ebe9c146101b1575b600080fd5b61014e610149366004612b43565b6102ed565b60405190151581526020015b60405180910390f35b610176610171366004612c66565b6103d2565b005b6101a3610186366004612d00565b805160208183018101805160428252928201919093012091525481565b60405190815260200161015a565b6101766101bf366004612d81565b6104bb565b6101766104cf565b6101766101da366004612e12565b610532565b60005460ff1661014e565b6101f26106fd565b60405161015a9190612ec1565b6102267f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b610176610259366004612e12565b61070f565b61017661026c366004612ed4565b610857565b610176610a75565b610176610287366004612f4e565b610ad6565b61014e61029a366004612fad565b610b56565b6101766102ad366004612ffd565b611010565b6101a36102c0366004612f4e565b60436020526000908152604090205481565b6101a3611055565b6101766102e836600461303f565b611284565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000148061038057507fffffffff0000000000000000000000000000000000000000000000000000000082167fab41c72e00000000000000000000000000000000000000000000000000000000145b806103cc57507fffffffff0000000000000000000000000000000000000000000000000000000082167fa4c0ed3600000000000000000000000000000000000000000000000000000000145b92915050565b6103da6117d5565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906323b872dd90606401602060405180830381600087803b15801561046e57600080fd5b505af1158015610482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a69190613103565b506104b48585858585611842565b5050505050565b6104c9600085858585610857565b50505050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461052857600080fd5b6105306122c5565b565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461058b57600080fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff808416916339f47693917f000000000000000000000000000000000000000000000000000000000000000091908516906370a082319060240160206040518083038186803b15801561061d57600080fd5b505afa158015610631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106559190613125565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401602060405180830381600087803b1580156106c057600080fd5b505af11580156106d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f89190613125565b505050565b606061070a604154612342565b905090565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461076857600080fd5b8173ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161415610849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4465706f736974436f6e74726163743a206e6f7420616c6c6f77656420746f2060448201527f636c61696d206465706f73697420746f6b656e0000000000000000000000000060648201526084015b60405180910390fd5b61085382826125b6565b5050565b3373fffffffffffffffffffffffffffffffffffffffe14806108c557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f546869732066756e6374696f6e2073686f756c642062652063616c6c6564206f60448201527f6e6c792062792053595354454d5f5749544844524157414c5f4558454355544f60648201527f52206f72205f61646d696e282900000000000000000000000000000000000000608482015260a401610840565b8281146109865761098661313e565b60005b83811015610a6d57600060208686848181106109a7576109a761316d565b90506020020160208101906109bc919061319c565b6109d49067ffffffffffffffff16633b9aca006131f5565b6109de9190613261565b905080604360008686868181106109f7576109f761316d565b9050602002016020810190610a0c9190612f4e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610a559190613275565b90915550610a66915082905061328d565b9050610989565b505050505050565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610ace57600080fd5b6105306125e4565b73ffffffffffffffffffffffffffffffffffffffff811660009081526043602052604090205480156108535773ffffffffffffffffffffffffffffffffffffffff808316600090815260436020526040812055610853907f000000000000000000000000000000000000000000000000000000000000000016838361263f565b6000610b606117d5565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4465706f736974436f6e74726163743a206e6f742061206465706f736974207460448201527f6f6b656e000000000000000000000000000000000000000000000000000000006064820152608401610840565b610c2f60b0836132c6565b602014610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4465706f736974436f6e74726163743a20696e636f7272656374206465706f7360448201527f69742064617461206c656e6774680000000000000000000000000000000000006064820152608401610840565b6000610ccb60b084613261565b905060008111610d5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f42617463684465706f7369743a20596f752073686f756c64206465706f73697460448201527f206174206c65617374206f6e652076616c696461746f720000000000000000006064820152608401610840565b846001821115610ea3576080821115610df8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f42617463684465706f7369743a20596f752063616e206465706f736974206d6160448201527f78203132382076616c696461746f727320617420612074696d650000000000006064820152608401610840565b610e0a82670de0b6b3a76400006131f5565b8614610e98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f42617463684465706f7369743a206261746368206465706f736974732072657160448201527f75697265203120474e4f206465706f73697420616d6f756e74000000000000006064820152608401610840565b50670de0b6b3a76400005b6000610eb260208287896132da565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293506020925050505b85811015610fff576000878288610f05826030613275565b92610f12939291906132da565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394508b92508a9150610f589050856030613275565b90610f64866090613275565b92610f71939291906132da565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394508c92508b9150610fb79050866090613275565b90610fc38760b0613275565b92610fd0939291906132da565b610fd991613304565b9050610fe8838684848a611842565b50505060b081610ff89190613275565b9050610eed565b50600193505050505b949350505050565b60005b818110156106f8576110458383838181106110305761103061316d565b90506020020160208101906102879190612f4e565b61104e8161328d565b9050611013565b6041546000908190815b60208110156111e257816001166001141561111e576002602182602081106110895761108961316d565b01546040805160208101929092528101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526110d791613340565b602060405180830381855afa1580156110f4573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111179190613125565b92506111c3565b600283600183602081106111345761113461316d565b0154604080516020810193909352820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261118091613340565b602060405180830381855afa15801561119d573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906111c09190613125565b92505b6111ce600283613261565b9150806111da8161328d565b91505061105f565b506002826111f1604154612342565b60405161120592919060009060200161335c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261123d91613340565b602060405180830381855afa15801561125a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061127d9190613125565b9250505090565b61128c6117d5565b808061131a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f42617463684465706f7369743a20596f752073686f756c64206465706f73697460448201527f206174206c65617374206f6e652076616c696461746f720000000000000000006064820152608401610840565b60808111156113ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f42617463684465706f7369743a20596f752063616e206465706f736974206d6160448201527f78203132382076616c696461746f727320617420612074696d650000000000006064820152608401610840565b6113b68160306131f5565b8814611444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f42617463684465706f7369743a205075626b657920636f756e7420646f6e277460448201527f206d6174636800000000000000000000000000000000000000000000000000006064820152608401610840565b61144f8160606131f5565b84146114dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f42617463684465706f7369743a205369676e61747572657320636f756e74206460448201527f6f6e2774206d61746368000000000000000000000000000000000000000000006064820152608401610840565b6020861461156d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f42617463684465706f7369743a205769746864726177616c2043726564656e7460448201527f69616c7320636f756e7420646f6e2774206d61746368000000000000000000006064820152608401610840565b670de0b6b3a764000073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166323b872dd33306115be86866131f5565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529290911660248301526044820152606401602060405180830381600087803b15801561163257600080fd5b505af1158015611646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166a9190613103565b5060005b828110156117c85760008b8b6116858460306131f5565b90611691856001613275565b61169c9060306131f5565b926116a9939291906132da565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394508b92508a91506116ef90508560606131f5565b906116fb866001613275565b6117069060606131f5565b92611713939291906132da565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506117b5828c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508692508c91508b9050888181106117a8576117a861316d565b9050602002013588611842565b5050806117c19061328d565b905061166e565b5050505050505050505050565b60005460ff1615610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610840565b61184d8160206131f5565b905084516030146118e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4465706f736974436f6e74726163743a20696e76616c6964207075626b65792060448201527f6c656e67746800000000000000000000000000000000000000000000000000006064820152608401610840565b8351602014611971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4465706f736974436f6e74726163743a20696e76616c6964207769746864726160448201527f77616c5f63726564656e7469616c73206c656e677468000000000000000000006064820152608401610840565b8251606014611a02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4465706f736974436f6e74726163743a20696e76616c6964207369676e61747560448201527f7265206c656e67746800000000000000000000000000000000000000000000006064820152608401610840565b670de0b6b3a7640000811015611a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4465706f736974436f6e74726163743a206465706f7369742076616c7565207460448201527f6f6f206c6f7700000000000000000000000000000000000000000000000000006064820152608401610840565b611aa8633b9aca00826132c6565b15611b35576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4465706f736974436f6e74726163743a206465706f7369742076616c7565206e60448201527f6f74206d756c7469706c65206f662067776569000000000000000000000000006064820152608401610840565b6000611b45633b9aca0083613261565b905067ffffffffffffffff811115611bdf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4465706f736974436f6e74726163743a206465706f7369742076616c7565207460448201527f6f6f2068696768000000000000000000000000000000000000000000000000006064820152608401610840565b6000611bea82612342565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c587878388611c1c604154612342565b604051611c2d9594939291906133b0565b60405180910390a16000600288600060801b604051602001611c5092919061341d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611c8891613340565b602060405180830381855afa158015611ca5573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611cc89190613125565b9050600086806020019051810190611ce09190613464565b90506000600280838360200201518460016020020151604051602001611d10929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611d4891613340565b602060405180830381855afa158015611d65573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611d889190613125565b60408481015181516020810191909152600081830152815180820383018152606090910191829052600291611dbd9190613340565b602060405180830381855afa158015611dda573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611dfd9190613125565b604080516020810193909352820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e4791613340565b602060405180830381855afa158015611e64573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611e879190613125565b90506000600280858c604051602001611ea19291906134e2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611ed991613340565b602060405180830381855afa158015611ef6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611f199190613125565b604051600290611f329089906000908890602001613508565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611f6a91613340565b602060405180830381855afa158015611f87573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611faa9190613125565b604080516020810193909352820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611ff491613340565b602060405180830381855afa158015612011573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906120349190613125565b90508781146120eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605460248201527f4465706f736974436f6e74726163743a207265636f6e7374727563746564204460448201527f65706f7369744461746120646f6573206e6f74206d6174636820737570706c6960648201527f6564206465706f7369745f646174615f726f6f74000000000000000000000000608482015260a401610840565b60016120f960206002613677565b6121039190613683565b60415410612193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c60448201527f6c000000000000000000000000000000000000000000000000000000000000006064820152608401610840565b6001604160008282546121a69190613275565b909155505060415460005b60208110156122ae5781600116600114156121ea5782602182602081106121da576121da61316d565b0155506104b49650505050505050565b6002602182602081106121ff576121ff61316d565b01546040805160208101929092528101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261224d91613340565b602060405180830381855afa15801561226a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061228d9190613125565b925061229a600283613261565b9150806122a68161328d565b9150506121b1565b506122b761313e565b505050505050505050505050565b6122cd6126cc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106123825761238261316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b826001815181106123cb576123cb61316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b826002815181106124145761241461316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b8260038151811061245d5761245d61316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b826004815181106124a6576124a661316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b826005815181106124ef576124ef61316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b826006815181106125385761253861316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106125815761258161316d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b73ffffffffffffffffffffffffffffffffffffffff82166125da5761085381612738565b610853828261277d565b6125ec6117d5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586123183390565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526106f89084906128c9565b60005460ff16610530576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610840565b604051479073ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156106f8573d6000803e3d6000fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8416906370a082319060240160206040518083038186803b1580156127e557600080fd5b505afa1580156127f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281d9190613125565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390529192509084169063a9059cbb90604401602060405180830381600087803b15801561289157600080fd5b505af11580156128a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c99190613103565b600061292b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166129d59092919063ffffffff16565b8051909150156106f857808060200190518101906129499190613103565b6106f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610840565b60606110088484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051612a099190613340565b60006040518083038185875af1925050503d8060008114612a46576040519150601f19603f3d011682016040523d82523d6000602084013e612a4b565b606091505b5091509150612a5c87838387612a67565b979650505050505050565b60608315612afa578251612af35773ffffffffffffffffffffffffffffffffffffffff85163b612af3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610840565b5081611008565b6110088383815115612b0f5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108409190612ec1565b600060208284031215612b5557600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612b8557600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112612bcc57600080fd5b813567ffffffffffffffff80821115612be757612be7612b8c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612c2d57612c2d612b8c565b81604052838152866020858801011115612c4657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a08688031215612c7e57600080fd5b853567ffffffffffffffff80821115612c9657600080fd5b612ca289838a01612bbb565b96506020880135915080821115612cb857600080fd5b612cc489838a01612bbb565b95506040880135915080821115612cda57600080fd5b50612ce788828901612bbb565b9598949750949560608101359550608001359392505050565b600060208284031215612d1257600080fd5b813567ffffffffffffffff811115612d2957600080fd5b61100884828501612bbb565b60008083601f840112612d4757600080fd5b50813567ffffffffffffffff811115612d5f57600080fd5b6020830191508360208260051b8501011115612d7a57600080fd5b9250929050565b60008060008060408587031215612d9757600080fd5b843567ffffffffffffffff80821115612daf57600080fd5b612dbb88838901612d35565b90965094506020870135915080821115612dd457600080fd5b50612de187828801612d35565b95989497509550505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e0f57600080fd5b50565b60008060408385031215612e2557600080fd5b8235612e3081612ded565b91506020830135612e4081612ded565b809150509250929050565b60005b83811015612e66578181015183820152602001612e4e565b838111156104c95750506000910152565b60008151808452612e8f816020860160208601612e4b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612b856020830184612e77565b600080600080600060608688031215612eec57600080fd5b85359450602086013567ffffffffffffffff80821115612f0b57600080fd5b612f1789838a01612d35565b90965094506040880135915080821115612f3057600080fd5b50612f3d88828901612d35565b969995985093965092949392505050565b600060208284031215612f6057600080fd5b8135612b8581612ded565b60008083601f840112612f7d57600080fd5b50813567ffffffffffffffff811115612f9557600080fd5b602083019150836020828501011115612d7a57600080fd5b60008060008060608587031215612fc357600080fd5b8435612fce81612ded565b935060208501359250604085013567ffffffffffffffff811115612ff157600080fd5b612de187828801612f6b565b6000806020838503121561301057600080fd5b823567ffffffffffffffff81111561302757600080fd5b61303385828601612d35565b90969095509350505050565b6000806000806000806000806080898b03121561305b57600080fd5b883567ffffffffffffffff8082111561307357600080fd5b61307f8c838d01612f6b565b909a50985060208b013591508082111561309857600080fd5b6130a48c838d01612f6b565b909850965060408b01359150808211156130bd57600080fd5b6130c98c838d01612f6b565b909650945060608b01359150808211156130e257600080fd5b506130ef8b828c01612d35565b999c989b5096995094979396929594505050565b60006020828403121561311557600080fd5b81518015158114612b8557600080fd5b60006020828403121561313757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156131ae57600080fd5b813567ffffffffffffffff81168114612b8557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561322d5761322d6131c6565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261327057613270613232565b500490565b60008219821115613288576132886131c6565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156132bf576132bf6131c6565b5060010190565b6000826132d5576132d5613232565b500690565b600080858511156132ea57600080fd5b838611156132f757600080fd5b5050820193919092039150565b803560208310156103cc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b60008251613352818460208701612e4b565b9190910192915050565b83815260008351613374816020850160208801612e4b565b80830190507fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008416602082015260388101915050949350505050565b60a0815260006133c360a0830188612e77565b82810360208401526133d58188612e77565b905082810360408401526133e98187612e77565b905082810360608401526133fd8186612e77565b905082810360808401526134118185612e77565b98975050505050505050565b6000835161342f818460208801612e4b565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000939093169190920190815260100192915050565b60006060828403121561347657600080fd5b82601f83011261348557600080fd5b6040516060810181811067ffffffffffffffff821117156134a8576134a8612b8c565b6040528060608401858111156134bd57600080fd5b845b818110156134d75780518352602092830192016134bf565b509195945050505050565b828152600082516134fa816020850160208701612e4b565b919091016020019392505050565b6000845161351a818460208901612e4b565b7fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009490941691909301908152601881019190915260380192915050565b600181815b808511156135b057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613596576135966131c6565b808516156135a357918102915b93841c939080029061355c565b509250929050565b6000826135c7575060016103cc565b816135d4575060006103cc565b81600181146135ea57600281146135f457613610565b60019150506103cc565b60ff841115613605576136056131c6565b50506001821b6103cc565b5060208310610133831016604e8410600b8410161715613633575081810a6103cc565b61363d8383613557565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561366f5761366f6131c6565b029392505050565b6000612b8583836135b8565b600082821015613695576136956131c6565b50039056fea26469706673582212203ce20f2f56588a2b91a30cd55aa2ef0ce265594100ba89ba293e06012ab7a20a64736f6c63430008090033" +} \ No newline at end of file diff --git a/test/shared/constants.ts b/test/shared/constants.ts index c6b2081b..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 = ONE_DAY +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' diff --git a/test/shared/contracts.ts b/test/shared/contracts.ts index c5a4a1e2..8a4cba52 100644 --- a/test/shared/contracts.ts +++ b/test/shared/contracts.ts @@ -1,7 +1,37 @@ import { ContractFactory } from 'ethers' import { ethers } from 'hardhat' -import { ethValidatorsRegistry } from '../../helpers/constants' +import EthValidatorsRegistry from './artifacts/EthValidatorsRegistry.json' +import GnoValidatorsRegistry from './artifacts/GnoValidatorsRegistry.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) +export async function getEthValidatorsRegistryFactory(): Promise { + return await ethers.getContractFactory(EthValidatorsRegistry.abi, EthValidatorsRegistry.bytecode) +} + +export async function getGnoValidatorsRegistryFactory(): Promise { + return await ethers.getContractFactory(GnoValidatorsRegistry.abi, GnoValidatorsRegistry.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..8de3f899 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, @@ -28,27 +33,26 @@ import { IKeeperRewards, Keeper, Keeper__factory, + LegacyRewardTokenMock, + LegacyRewardTokenMock__factory, OsToken, OsToken__factory, - OsTokenVaultController, - OsTokenVaultController__factory, OsTokenConfig, OsTokenConfig__factory, + OsTokenVaultController, + OsTokenVaultController__factory, PoolEscrowMock, PoolEscrowMock__factory, PriceFeed, PriceFeed__factory, - RewardEthTokenMock, - RewardEthTokenMock__factory, RewardSplitterFactory, RewardSplitterFactory__factory, SharedMevEscrow, SharedMevEscrow__factory, VaultsRegistry, VaultsRegistry__factory, - EthFoxVault__factory, } from '../../typechain-types' -import { getValidatorsRegistryFactory } from './contracts' +import { getEthValidatorsRegistryFactory } from './contracts' import { EXITING_ASSETS_MIN_DELAY, MAX_AVG_REWARD_PER_SECOND, @@ -68,7 +72,7 @@ import { SECURITY_DEPOSIT, VALIDATORS_MIN_ORACLES, } from './constants' -import { EthErc20VaultInitParamsStruct, EthVaultInitParamsStruct } 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' @@ -103,9 +107,20 @@ export const transferOwnership = async function ( await contract.connect(newOwner).acceptOwnership() } +export const upgradeVault = async function ( + vault: EthVaultType, + 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: EthVaultType, 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: EthVaultType): Promise { const depositorMockFactory = await ethers.getContractFactory('DepositorMock') const contract = await depositorMockFactory.deploy(await vault.getAddress()) return DepositorMock__factory.connect( @@ -144,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) { @@ -188,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() @@ -379,22 +392,22 @@ export const createEthVaultFactory = async function ( ) } -export const deployGenesisVaultImpl = async function ( +export const deployEthGenesisVaultImpl = async function ( keeper: Keeper, vaultsRegistry: VaultsRegistry, validatorsRegistry: Contract, - osToken: OsToken, + osTokenVaultController: OsTokenVaultController, osTokenConfig: OsTokenConfig, sharedMevEscrow: SharedMevEscrow, poolEscrow: PoolEscrowMock, - rewardEthToken: RewardEthTokenMock + rewardEthToken: LegacyRewardTokenMock ): Promise { const factory = await ethers.getContractFactory('EthGenesisVault') const constructorArgs = [ await keeper.getAddress(), await vaultsRegistry.getAddress(), await validatorsRegistry.getAddress(), - await osToken.getAddress(), + await osTokenVaultController.getAddress(), await osTokenConfig.getAddress(), await sharedMevEscrow.getAddress(), await poolEscrow.getAddress(), @@ -407,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, @@ -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)'], @@ -491,10 +542,11 @@ interface EthVaultFixture { sharedMevEscrow: SharedMevEscrow validatorsRegistry: Contract ethVaultFactory: EthVaultFactory - ethVaultMockFactory: EthVaultFactory ethPrivVaultFactory: EthVaultFactory ethErc20VaultFactory: EthVaultFactory ethPrivErc20VaultFactory: EthVaultFactory + ethBlocklistVaultFactory: EthVaultFactory + ethBlocklistErc20VaultFactory: EthVaultFactory osToken: OsToken osTokenVaultController: OsTokenVaultController osTokenConfig: OsTokenConfig @@ -509,7 +561,7 @@ interface EthVaultFixture { createEthFoxVault(admin: Signer, vaultParams: EthVaultInitParamsStruct): Promise createEthVaultMock( - admin: Wallet, + admin: Signer, vaultParams: EthVaultInitParamsStruct, isOwnMevEscrow?: boolean ): Promise @@ -520,6 +572,12 @@ interface EthVaultFixture { isOwnMevEscrow?: boolean ): Promise + createEthBlocklistVault( + admin: Signer, + vaultParams: EthVaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + createEthErc20Vault( admin: Signer, vaultParams: EthErc20VaultInitParamsStruct, @@ -533,19 +591,25 @@ interface EthVaultFixture { isOwnMevEscrow?: boolean ): Promise + createEthBlocklistErc20Vault( + admin: Signer, + vaultParams: EthErc20VaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + createEthGenesisVault( 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({ @@ -617,9 +681,11 @@ export const ethVaultFixture = async function (): Promise { 'EthPrivVault', 'EthErc20Vault', 'EthPrivErc20Vault', + 'EthBlocklistVault', + 'EthBlocklistErc20Vault', 'EthVaultMock', ]) { - const vaultImpl = await deployVaultImplementation( + const vaultImpl = await deployEthVaultImplementation( vaultType, keeper, vaultsRegistry, @@ -645,7 +711,8 @@ export const ethVaultFixture = async function (): Promise { const ethPrivVaultFactory = factories['EthPrivVault'] const ethErc20VaultFactory = factories['EthErc20Vault'] const ethPrivErc20VaultFactory = factories['EthPrivErc20Vault'] - const ethVaultMockFactory = factories['EthVaultMock'] + const ethBlocklistVaultFactory = factories['EthBlocklistVault'] + const ethBlocklistErc20VaultFactory = factories['EthBlocklistErc20Vault'] return { vaultsRegistry, @@ -656,7 +723,8 @@ export const ethVaultFixture = async function (): Promise { ethPrivVaultFactory, ethErc20VaultFactory, ethPrivErc20VaultFactory, - ethVaultMockFactory, + ethBlocklistVaultFactory, + ethBlocklistErc20VaultFactory, osTokenVaultController, osTokenConfig, osToken, @@ -681,6 +749,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethVaultSharedMevEscrow } const vault = EthVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVault(vault, implementations['EthVault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -733,11 +802,11 @@ export const ethVaultFixture = async function (): Promise { return vault }, createEthVaultMock: async ( - admin: Wallet, + admin: Signer, vaultParams: EthVaultInitParamsStruct, isOwnMevEscrow = false ): Promise => { - const tx = await ethVaultMockFactory + const tx = await factories['EthVaultMock'] .connect(admin) .createVault(encodeEthVaultInitParams(vaultParams), isOwnMevEscrow, { value: SECURITY_DEPOSIT, @@ -765,10 +834,24 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethPrivVaultSharedMevEscrow } const vault = EthPrivVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVault(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 +873,7 @@ export const ethVaultFixture = async function (): Promise { vaultAddress = MAINNET_FORK.vaults.ethErc20VaultSharedMevEscrow } const vault = EthErc20Vault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + await upgradeVault(vault, implementations['EthErc20Vault']) await updateVaultState(keeper, vault, MAINNET_FORK.harvestParams[vaultAddress]) await setBalance(await vault.admin(), parseEther('1000')) return vault @@ -817,36 +901,54 @@ export const ethVaultFixture = async function (): Promise { vaultAddress, await ethers.provider.getSigner() ) + await upgradeVault(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, 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, - osToken, + osTokenVaultController, osTokenConfig, sharedMevEscrow, poolEscrow, @@ -879,6 +981,7 @@ export const ethVaultFixture = async function (): Promise { mainnetDeployment.EthGenesisVault, await ethers.provider.getSigner() ) + await upgradeVault(vault, vaultImpl) await updateVaultState( keeper, vault, diff --git a/test/shared/gnoFixtures.ts b/test/shared/gnoFixtures.ts new file mode 100644 index 00000000..0bdeb612 --- /dev/null +++ b/test/shared/gnoFixtures.ts @@ -0,0 +1,655 @@ +import hre, { ethers } from 'hardhat' +import { + BigNumberish, + Contract, + ContractTransactionResponse, + parseEther, + Signer, + Wallet, +} from 'ethers' +import { simulateDeployImpl } from '@openzeppelin/hardhat-upgrades/dist/utils' +import EthereumWallet from 'ethereumjs-wallet' +import { + BalancerVaultMock, + BalancerVaultMock__factory, + ERC20Mock, + ERC20Mock__factory, + GnoBlocklistErc20Vault, + GnoBlocklistErc20Vault__factory, + GnoBlocklistVault, + GnoBlocklistVault__factory, + GnoErc20Vault, + GnoErc20Vault__factory, + GnoGenesisVault, + GnoGenesisVault__factory, + GnoPrivErc20Vault, + GnoPrivErc20Vault__factory, + GnoPrivVault, + GnoPrivVault__factory, + GnoSharedMevEscrow, + GnoVault, + GnoVault__factory, + GnoVaultFactory, + GnoVaultFactory__factory, + Keeper, + LegacyRewardTokenMock, + LegacyRewardTokenMock__factory, + OsToken, + OsTokenConfig, + OsTokenVaultController, + PoolEscrowMock, + SharedMevEscrow, + SharedMevEscrow__factory, + VaultsRegistry, + XdaiExchange, + XdaiExchange__factory, +} from '../../typechain-types' +import { getGnoValidatorsRegistryFactory } from './contracts' +import { + EXITING_ASSETS_MIN_DELAY, + MAX_AVG_REWARD_PER_SECOND, + ORACLES, + ORACLES_CONFIG, + OSTOKEN_CAPACITY, + OSTOKEN_FEE, + OSTOKEN_LIQ_BONUS, + OSTOKEN_LIQ_THRESHOLD, + OSTOKEN_LTV, + OSTOKEN_NAME, + OSTOKEN_REDEEM_FROM_LTV, + OSTOKEN_REDEEM_TO_LTV, + OSTOKEN_SYMBOL, + REWARDS_DELAY, + REWARDS_MIN_ORACLES, + SECURITY_DEPOSIT, + VALIDATORS_MIN_ORACLES, + ZERO_ADDRESS, + ZERO_BYTES32, +} from './constants' +import { GnoErc20VaultInitParamsStruct, GnoVaultInitParamsStruct, GnoVaultType } from './types' +import { + extractDepositShares, + extractExitPositionTicket, + extractVaultAddress, + getBlockTimestamp, + increaseTime, + setBalance, +} from './utils' +import { + createKeeper, + createOsToken, + createOsTokenConfig, + createOsTokenVaultController, + createPoolEscrow, + createVaultsRegistry, + transferOwnership, +} from './fixtures' +import { registerEthValidator } from './validators' + +export const setGnoWithdrawals = async function ( + validatorsRegistry: Contract, + gnoToken: ERC20Mock, + vault: GnoVault | PoolEscrowMock, + withdrawals: bigint +): Promise { + const systemAddr = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE' + const system = await ethers.getImpersonatedSigner(systemAddr) + await setBalance(systemAddr, ethers.parseEther('1')) + await gnoToken.mint(await validatorsRegistry.getAddress(), withdrawals) + await validatorsRegistry + .connect(system) + .executeSystemWithdrawals( + [(withdrawals * parseEther('32')) / parseEther('1') / 1000000000n], + [await vault.getAddress()] + ) +} + +export async function collateralizeGnoVault( + vault: GnoVaultType, + gnoToken: ERC20Mock, + keeper: Keeper, + validatorsRegistry: Contract, + admin: Wallet, + genesisVaultPoolEscrow: string | null = null +) { + const adminAddr = await admin.getAddress() + + // register validator + const validatorDeposit = ethers.parseEther('1') + const tx = await depositGno(vault, gnoToken, validatorDeposit, admin, admin, ZERO_ADDRESS) + const receivedShares = await extractDepositShares(tx) + await registerEthValidator(vault, keeper, validatorsRegistry, admin, genesisVaultPoolEscrow) + + // 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 setGnoWithdrawals(validatorsRegistry, gnoToken, vault, validatorDeposit) + + // claim exited assets + await vault.connect(admin).claimExitedAssets(positionTicket, timestamp, 0) +} + +export const depositGno = async function ( + vault: GnoVault, + gnoToken: ERC20Mock, + assets: bigint, + sender: Wallet, + receiver: Wallet, + referrer: string +): Promise { + await gnoToken.mint(await sender.getAddress(), assets) + await gnoToken.connect(sender).approve(await vault.getAddress(), assets) + return await vault.connect(sender).deposit(assets, await receiver.getAddress(), referrer) +} + +export const createGnoValidatorsRegistry = async function (gnoToken: ERC20Mock): Promise { + const validatorsRegistryFactory = await getGnoValidatorsRegistryFactory() + const signer = await ethers.provider.getSigner() + const contract = await validatorsRegistryFactory.deploy(await gnoToken.getAddress()) + return new Contract(await contract.getAddress(), validatorsRegistryFactory.interface, signer) +} + +export const approveSecurityDeposit = async function ( + approvedAddr: string, + gnoToken: ERC20Mock, + admin: Signer +): Promise { + await gnoToken.mint(await admin.getAddress(), SECURITY_DEPOSIT) + await gnoToken.connect(admin).approve(approvedAddr, SECURITY_DEPOSIT) +} + +export const createGnoSharedMevEscrow = async function ( + vaultsRegistry: VaultsRegistry +): Promise { + const signer = await ethers.provider.getSigner() + const factory = await ethers.getContractFactory('GnoSharedMevEscrow') + const contract = await factory.deploy(await vaultsRegistry.getAddress()) + return SharedMevEscrow__factory.connect(await contract.getAddress(), signer) +} + +export const createBalancerVaultMock = async function ( + gnoToken: ERC20Mock, + daiGnoRate: BigNumberish, + dao: Signer +): Promise { + const factory = await ethers.getContractFactory('BalancerVaultMock') + const contract = await factory.deploy( + await gnoToken.getAddress(), + daiGnoRate, + await dao.getAddress() + ) + return BalancerVaultMock__factory.connect(await contract.getAddress(), dao) +} + +export const createXdaiExchange = async function ( + gnoToken: ERC20Mock, + balancerVault: BalancerVaultMock, + balancerPoolId: string, + vaultsRegistry: VaultsRegistry, + dao: Signer +): Promise { + const factory = await ethers.getContractFactory('XdaiExchange') + + const constructorArgs = [ + await gnoToken.getAddress(), + balancerPoolId, + await balancerVault.getAddress(), + await vaultsRegistry.getAddress(), + ] + const contract = await factory.deploy(...constructorArgs) + const impl = await contract.getAddress() + await simulateDeployImpl(hre, factory, { constructorArgs }, impl) + + const proxyFactory = await ethers.getContractFactory('ERC1967Proxy') + const proxy = await proxyFactory.deploy(impl, '0x') + const proxyAddress = await proxy.getAddress() + const xdaiExchange = XdaiExchange__factory.connect(proxyAddress, dao) + await xdaiExchange.initialize(await dao.getAddress()) + return xdaiExchange +} + +export const createGnoVaultFactory = async function ( + implementation: string, + vaultsRegistry: VaultsRegistry, + gnoToken: ERC20Mock +): Promise { + const factory = await ethers.getContractFactory('GnoVaultFactory') + const contract = await factory.deploy( + implementation, + await vaultsRegistry.getAddress(), + await gnoToken.getAddress() + ) + return GnoVaultFactory__factory.connect( + await contract.getAddress(), + await ethers.provider.getSigner() + ) +} + +export const deployGnoGenesisVaultImpl = async function ( + keeper: Keeper, + vaultsRegistry: VaultsRegistry, + validatorsRegistry: Contract, + osTokenVaultController: OsTokenVaultController, + osTokenConfig: OsTokenConfig, + sharedMevEscrow: SharedMevEscrow, + gnoToken: ERC20Mock, + xdaiExchange: XdaiExchange, + poolEscrow: PoolEscrowMock, + rewardGnoToken: LegacyRewardTokenMock +): Promise { + const factory = await ethers.getContractFactory('GnoGenesisVault') + const constructorArgs = [ + await keeper.getAddress(), + await vaultsRegistry.getAddress(), + await validatorsRegistry.getAddress(), + await osTokenVaultController.getAddress(), + await osTokenConfig.getAddress(), + await sharedMevEscrow.getAddress(), + await gnoToken.getAddress(), + await xdaiExchange.getAddress(), + await poolEscrow.getAddress(), + await rewardGnoToken.getAddress(), + EXITING_ASSETS_MIN_DELAY, + ] + const contract = await factory.deploy(...constructorArgs) + const vaultImpl = await contract.getAddress() + await simulateDeployImpl(hre, factory, { constructorArgs }, vaultImpl) + return vaultImpl +} + +export const deployGnoVaultImplementation = async function ( + vaultType: string, + keeper: Keeper, + vaultsRegistry: VaultsRegistry, + validatorsRegistry: string, + osTokenVaultController: OsTokenVaultController, + osTokenConfig: OsTokenConfig, + sharedMevEscrow: GnoSharedMevEscrow, + gnoToken: ERC20Mock, + xdaiExchange: XdaiExchange, + exitingAssetsMinDelay: number +): Promise { + const factory = await ethers.getContractFactory(vaultType) + const constructorArgs = [ + await keeper.getAddress(), + await vaultsRegistry.getAddress(), + validatorsRegistry, + await osTokenVaultController.getAddress(), + await osTokenConfig.getAddress(), + await sharedMevEscrow.getAddress(), + await gnoToken.getAddress(), + await xdaiExchange.getAddress(), + exitingAssetsMinDelay, + ] + const contract = await factory.deploy(...constructorArgs) + const vaultImpl = await contract.getAddress() + await simulateDeployImpl(hre, factory, { constructorArgs }, vaultImpl) + return vaultImpl +} + +export const encodeGnoVaultInitParams = function (vaultParams: GnoVaultInitParamsStruct): string { + return ethers.AbiCoder.defaultAbiCoder().encode( + ['tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)'], + [[vaultParams.capacity, vaultParams.feePercent, vaultParams.metadataIpfsHash]] + ) +} + +export const encodeGnoErc20VaultInitParams = function ( + vaultParams: GnoErc20VaultInitParamsStruct +): string { + return ethers.AbiCoder.defaultAbiCoder().encode( + [ + 'tuple(uint256 capacity, uint16 feePercent, string name, string symbol, string metadataIpfsHash)', + ], + [ + [ + vaultParams.capacity, + vaultParams.feePercent, + vaultParams.name, + vaultParams.symbol, + vaultParams.metadataIpfsHash, + ], + ] + ) +} + +interface GnoVaultFixture { + vaultsRegistry: VaultsRegistry + keeper: Keeper + sharedMevEscrow: SharedMevEscrow + validatorsRegistry: Contract + gnoVaultFactory: GnoVaultFactory + gnoPrivVaultFactory: GnoVaultFactory + gnoErc20VaultFactory: GnoVaultFactory + gnoPrivErc20VaultFactory: GnoVaultFactory + gnoBlocklistVaultFactory: GnoVaultFactory + gnoBlocklistErc20VaultFactory: GnoVaultFactory + osToken: OsToken + osTokenVaultController: OsTokenVaultController + osTokenConfig: OsTokenConfig + xdaiExchange: XdaiExchange + gnoToken: ERC20Mock + balancerVault: BalancerVaultMock + + createGnoVault( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoPrivVault( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoBlocklistVault( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoErc20Vault( + admin: Signer, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoPrivErc20Vault( + admin: Signer, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoBlocklistErc20Vault( + admin: Signer, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow?: boolean + ): Promise + + createGnoGenesisVault( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct + ): Promise<[GnoGenesisVault, LegacyRewardTokenMock, PoolEscrowMock]> +} + +export const gnoVaultFixture = async function (): Promise { + const dao = await (ethers as any).provider.getSigner() + const vaultsRegistry = await createVaultsRegistry() + + const factory = await ethers.getContractFactory('ERC20Mock') + const contract = await factory.connect(dao).deploy() + const gnoToken = ERC20Mock__factory.connect(await contract.getAddress(), dao) + const validatorsRegistry = await createGnoValidatorsRegistry(gnoToken) + + const sharedMevEscrow = await createGnoSharedMevEscrow(vaultsRegistry) + + // 1. calc osToken address + const _osTokenAddress = ethers.getCreateAddress({ + from: dao.address, + nonce: (await ethers.provider.getTransactionCount(dao.address)) + 1, + }) + + // 2. calc keeper address + const _keeperAddress = ethers.getCreateAddress({ + from: dao.address, + nonce: (await ethers.provider.getTransactionCount(dao.address)) + 2, + }) + + // 3. deploy osTokenVaultController + const osTokenVaultController = await createOsTokenVaultController( + _keeperAddress, + vaultsRegistry, + _osTokenAddress, + dao, + dao, + OSTOKEN_FEE, + OSTOKEN_CAPACITY + ) + + // 4. deploy osToken + const osToken = await createOsToken(dao, osTokenVaultController, OSTOKEN_NAME, OSTOKEN_SYMBOL) + if (_osTokenAddress != (await osToken.getAddress())) { + throw new Error('Invalid calculated OsToken address') + } + + // 5. deploy keeper + const sortedOracles = ORACLES.sort((oracle1, oracle2) => { + const oracle1Addr = new EthereumWallet(oracle1).getAddressString() + const oracle2Addr = new EthereumWallet(oracle2).getAddressString() + return oracle1Addr > oracle2Addr ? 1 : -1 + }) + const keeper = await createKeeper( + sortedOracles.map((s) => new EthereumWallet(s).getAddressString()), + ORACLES_CONFIG, + sharedMevEscrow, + vaultsRegistry, + osTokenVaultController, + REWARDS_DELAY, + MAX_AVG_REWARD_PER_SECOND, + REWARDS_MIN_ORACLES, + validatorsRegistry, + VALIDATORS_MIN_ORACLES + ) + if (_keeperAddress != (await keeper.getAddress())) { + throw new Error('Invalid calculated Keeper address') + } + + // 6. deploy osTokenConfig + const osTokenConfig = await createOsTokenConfig( + dao, + OSTOKEN_REDEEM_FROM_LTV, + OSTOKEN_REDEEM_TO_LTV, + OSTOKEN_LIQ_THRESHOLD, + OSTOKEN_LIQ_BONUS, + OSTOKEN_LTV + ) + + // 7. deploy Balancer vault + const balancerVault = await createBalancerVaultMock(gnoToken, parseEther('0.003'), dao) + + // 8. deploy XDai exchange + const xdaiExchange = await createXdaiExchange( + gnoToken, + balancerVault, + ZERO_BYTES32, + vaultsRegistry, + dao + ) + + // 9. deploy implementations and factories + const factories = {} + const implementations = {} + + for (const vaultType of [ + 'GnoVault', + 'GnoPrivVault', + 'GnoErc20Vault', + 'GnoPrivErc20Vault', + 'GnoBlocklistVault', + 'GnoBlocklistErc20Vault', + ]) { + const vaultImpl = await deployGnoVaultImplementation( + vaultType, + keeper, + vaultsRegistry, + await validatorsRegistry.getAddress(), + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + EXITING_ASSETS_MIN_DELAY + ) + await vaultsRegistry.addVaultImpl(vaultImpl) + implementations[vaultType] = vaultImpl + + const vaultFactory = await createGnoVaultFactory(vaultImpl, vaultsRegistry, gnoToken) + await vaultsRegistry.addFactory(await vaultFactory.getAddress()) + factories[vaultType] = vaultFactory + } + + // change ownership + await transferOwnership(vaultsRegistry, dao) + await transferOwnership(keeper, dao) + + const gnoVaultFactory = factories['GnoVault'] + const gnoPrivVaultFactory = factories['GnoPrivVault'] + const gnoErc20VaultFactory = factories['GnoErc20Vault'] + const gnoPrivErc20VaultFactory = factories['GnoPrivErc20Vault'] + const gnoBlocklistVaultFactory = factories['GnoBlocklistVault'] + const gnoBlocklistErc20VaultFactory = factories['GnoBlocklistErc20Vault'] + + return { + vaultsRegistry, + sharedMevEscrow, + keeper, + validatorsRegistry, + gnoVaultFactory, + gnoPrivVaultFactory, + gnoErc20VaultFactory, + gnoPrivErc20VaultFactory, + gnoBlocklistVaultFactory, + gnoBlocklistErc20VaultFactory, + osTokenVaultController, + osTokenConfig, + osToken, + xdaiExchange, + gnoToken, + balancerVault, + createGnoVault: async ( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit(await gnoVaultFactory.getAddress(), gnoToken, admin) + const tx = await gnoVaultFactory + .connect(admin) + .createVault(encodeGnoVaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, + createGnoPrivVault: async ( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit(await gnoPrivVaultFactory.getAddress(), gnoToken, admin) + const tx = await gnoPrivVaultFactory + .connect(admin) + .createVault(encodeGnoVaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoPrivVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, + createGnoBlocklistVault: async ( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit(await gnoBlocklistVaultFactory.getAddress(), gnoToken, admin) + const tx = await gnoBlocklistVaultFactory + .connect(admin) + .createVault(encodeGnoVaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoBlocklistVault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, + createGnoErc20Vault: async ( + admin: Signer, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit(await gnoErc20VaultFactory.getAddress(), gnoToken, admin) + const tx = await gnoErc20VaultFactory + .connect(admin) + .createVault(encodeGnoErc20VaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoErc20Vault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, + createGnoPrivErc20Vault: async ( + admin: Signer, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit(await gnoPrivErc20VaultFactory.getAddress(), gnoToken, admin) + const tx = await gnoPrivErc20VaultFactory + .connect(admin) + .createVault(encodeGnoErc20VaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoPrivErc20Vault__factory.connect(vaultAddress, await ethers.provider.getSigner()) + }, + createGnoBlocklistErc20Vault: async ( + admin: Wallet, + vaultParams: GnoErc20VaultInitParamsStruct, + isOwnMevEscrow = false + ): Promise => { + await approveSecurityDeposit( + await gnoBlocklistErc20VaultFactory.getAddress(), + gnoToken, + admin + ) + const tx = await gnoBlocklistErc20VaultFactory + .connect(admin) + .createVault(encodeGnoErc20VaultInitParams(vaultParams), isOwnMevEscrow) + const vaultAddress = await extractVaultAddress(tx) + return GnoBlocklistErc20Vault__factory.connect( + vaultAddress, + await ethers.provider.getSigner() + ) + }, + createGnoGenesisVault: async ( + admin: Signer, + vaultParams: GnoVaultInitParamsStruct + ): Promise<[GnoGenesisVault, LegacyRewardTokenMock, PoolEscrowMock]> => { + const poolEscrow = await createPoolEscrow(dao.address) + const legacyRewardTokenMockFactory = await ethers.getContractFactory('LegacyRewardTokenMock') + const legacyRewardTokenMock = await legacyRewardTokenMockFactory.deploy() + const rewardGnoToken = LegacyRewardTokenMock__factory.connect( + await legacyRewardTokenMock.getAddress(), + dao + ) + + const vaultImpl = await deployGnoGenesisVaultImpl( + keeper, + vaultsRegistry, + validatorsRegistry, + osTokenVaultController, + osTokenConfig, + sharedMevEscrow, + gnoToken, + xdaiExchange, + poolEscrow, + rewardGnoToken + ) + await vaultsRegistry.addVaultImpl(vaultImpl) + + const proxyFactory = await ethers.getContractFactory('ERC1967Proxy') + const proxy = await proxyFactory.deploy(vaultImpl, '0x') + const proxyAddress = await proxy.getAddress() + const vault = GnoGenesisVault__factory.connect( + proxyAddress, + await ethers.provider.getSigner() + ) + await rewardGnoToken.connect(dao).setVault(proxyAddress) + await poolEscrow.connect(dao).commitOwnershipTransfer(proxyAddress) + const adminAddr = await admin.getAddress() + await approveSecurityDeposit(await vault.getAddress(), gnoToken, admin) + + await vault + .connect(admin) + .initialize( + ethers.AbiCoder.defaultAbiCoder().encode( + ['address', 'tuple(uint256 capacity, uint16 feePercent, string metadataIpfsHash)'], + [ + adminAddr, + [vaultParams.capacity, vaultParams.feePercent, vaultParams.metadataIpfsHash], + ] + ) + ) + await vaultsRegistry.addVault(proxyAddress) + return [vault, rewardGnoToken, poolEscrow] + }, + } +} diff --git a/test/shared/rewards.ts b/test/shared/rewards.ts index f1b5ae95..404de1ae 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 { EthVaultType } 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: EthVaultType, + 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..0cf29cfd 100644 --- a/test/shared/types.ts +++ b/test/shared/types.ts @@ -1,9 +1,29 @@ +import { + EthErc20Vault, + EthFoxVault, + EthGenesisVault, + EthPrivErc20Vault, + EthPrivVault, + EthVault, + GnoVault, + GnoPrivVault, + GnoErc20Vault, + GnoPrivErc20Vault, + GnoGenesisVault, +} from '../../typechain-types' + export type EthVaultInitParamsStruct = { capacity: bigint feePercent: number metadataIpfsHash: string } +export type GnoVaultInitParamsStruct = { + capacity: bigint + feePercent: number + metadataIpfsHash: string +} + export type EthErc20VaultInitParamsStruct = { capacity: bigint feePercent: number @@ -11,3 +31,26 @@ export type EthErc20VaultInitParamsStruct = { symbol: string metadataIpfsHash: string } + +export type GnoErc20VaultInitParamsStruct = { + capacity: bigint + feePercent: number + name: string + symbol: string + metadataIpfsHash: string +} + +export type EthVaultType = + | EthVault + | EthPrivVault + | EthErc20Vault + | EthPrivErc20Vault + | EthGenesisVault + | EthFoxVault + +export type GnoVaultType = + | GnoVault + | GnoPrivVault + | GnoErc20Vault + | GnoPrivErc20Vault + | GnoGenesisVault diff --git a/test/shared/validators.ts b/test/shared/validators.ts index c8e24ff3..f32a63e3 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 { EthVaultType, GnoVaultType } from './types' export const secretKeys = [ '0x2c66340f2d886f3fc4cfef10a802ddbaf4a37ffb49533b604f8a50804e8d198f', @@ -143,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,10 +188,14 @@ export function appendDepositData( } export async function createEthValidatorsData( - vault: EthVault | EthFoxVault + vault: EthVaultType | GnoVaultType, + 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'] @@ -210,7 +214,7 @@ export async function getEthValidatorsSigningData( deadline: bigint, exitSignaturesIpfsHash: string, keeper: Keeper, - vault: EthVault | EthFoxVault, + vault: EthVaultType | GnoVaultType, validatorsRegistryRoot: BytesLike ) { return { @@ -278,7 +282,7 @@ export function getValidatorsMultiProof( } export async function registerEthValidator( - vault: EthVault | EthFoxVault, + vault: EthVaultType | GnoVaultType, keeper: Keeper, validatorsRegistry: Contract, admin: Signer