diff --git a/package.json b/package.json index 507d3aed1..76c37ac19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "3.11.10", + "version": "3.11.11", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", diff --git a/src/abi/SSPM.json b/src/abi/SSPM.json new file mode 100644 index 000000000..6842a14bf --- /dev/null +++ b/src/abi/SSPM.json @@ -0,0 +1,829 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotManager", + "type": "error" + }, + { + "inputs": [], + "name": "CallerNotStaderContract", + "type": "error" + }, + { + "inputs": [], + "name": "CooldownNotComplete", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDepositAmount", + "type": "error" + }, + { + "inputs": [], + "name": "PoolIdDoesNotExit", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedOperation", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedOperationInSafeMode", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AuctionedEthReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "referralId", + "type": "string" + } + ], + "name": "DepositReferral", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "assets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "shares", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "poolId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "poolAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorCount", + "type": "uint256" + } + ], + "name": "ETHTransferredToPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExecutionLayerRewardsReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + } + ], + "name": "ReceivedExcessEthFromPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredETHToUserWithdrawManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "excessETHDepositCoolDown", + "type": "uint256" + } + ], + "name": "UpdatedExcessETHDepositCoolDown", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "staderConfig", + "type": "address" + } + ], + "name": "UpdatedStaderConfig", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawVaultUserShareReceived", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_assets", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositETHOverTargetWeight", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "excessETHDepositCoolDown", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + }, + { + "internalType": "address", + "name": "_staderConfig", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isVaultHealthy", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastExcessETHDepositBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_assets", + "type": "uint256" + } + ], + "name": "previewDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "previewWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "receiveEthFromAuction", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_poolId", + "type": "uint8" + } + ], + "name": "receiveExcessEthFromPool", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "receiveExecutionLayerRewards", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "receiveWithdrawVaultUserShare", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staderConfig", + "outputs": [ + { + "internalType": "contract IStaderConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "transferETHToUserWithdrawManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_excessETHDepositCoolDown", + "type": "uint256" + } + ], + "name": "updateExcessETHDepositCoolDown", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_staderConfig", + "type": "address" + } + ], + "name": "updateStaderConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_poolId", + "type": "uint8" + } + ], + "name": "validatorBatchDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/src/abi/StaderOracle.json b/src/abi/StaderOracle.json new file mode 100644 index 000000000..442ce907d --- /dev/null +++ b/src/abi/StaderOracle.json @@ -0,0 +1,2170 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotManager", + "type": "error" + }, + { + "inputs": [], + "name": "CooldownNotComplete", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSubmissionFromNode", + "type": "error" + }, + { + "inputs": [], + "name": "ERChangeLimitCrossed", + "type": "error" + }, + { + "inputs": [], + "name": "ERChangeLimitNotCrossed", + "type": "error" + }, + { + "inputs": [], + "name": "ERPermissibleChangeOutofBounds", + "type": "error" + }, + { + "inputs": [], + "name": "FrequencyUnchanged", + "type": "error" + }, + { + "inputs": [], + "name": "InspectionModeActive", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientTrustedNodes", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidERDataSource", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMAPDIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMerkleRootIndex", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPubkeyLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReportingBlock", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidUpdate", + "type": "error" + }, + { + "inputs": [], + "name": "NodeAlreadyTrusted", + "type": "error" + }, + { + "inputs": [], + "name": "NodeNotTrusted", + "type": "error" + }, + { + "inputs": [], + "name": "NotATrustedNode", + "type": "error" + }, + { + "inputs": [], + "name": "PageNumberAlreadyReported", + "type": "error" + }, + { + "inputs": [], + "name": "ReportingFutureBlockData", + "type": "error" + }, + { + "inputs": [], + "name": "ReportingPreviousCycleData", + "type": "error" + }, + { + "inputs": [], + "name": "UpdateFrequencyNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroFrequency", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "isPORBasedERData", + "type": "bool" + } + ], + "name": "ERDataSourceToggled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "erInspectionMode", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ERInspectionModeActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalEth", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethxSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ExchangeRateSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalEth", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethxSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ExchangeRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + } + ], + "name": "MissedAttestationPenaltySubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + } + ], + "name": "MissedAttestationPenaltyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sdPriceInETH", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reportedBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + } + ], + "name": "SDPriceSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "sdPriceInETH", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reportedBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + } + ], + "name": "SDPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "SafeModeDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "SafeModeEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + } + ], + "name": "SocializingRewardsMerkleRootSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + } + ], + "name": "SocializingRewardsMerkleRootUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "TrustedNodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "trustedNodeChangeCoolingPeriod", + "type": "uint256" + } + ], + "name": "TrustedNodeChangeCoolingPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "TrustedNodeRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "updateFrequency", + "type": "uint256" + } + ], + "name": "UpdateFrequencyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "erChangeLimit", + "type": "uint256" + } + ], + "name": "UpdatedERChangeLimit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "staderConfig", + "type": "address" + } + ], + "name": "UpdatedStaderConfig", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "activeValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitedValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "slashedValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "activeValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitedValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "slashedValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ValidatorStatsSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "activeValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitedValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "slashedValidatorsBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "activeValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "exitedValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "slashedValidatorsCount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ValidatorStatsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedReadyToDepositPubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedFrontRunPubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedInvalidSignaturePubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ValidatorVerificationDetailSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedReadyToDepositPubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedFrontRunPubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "sortedInvalidSignaturePubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "ValidatorVerificationDetailUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "WithdrawnValidatorsSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "block", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "pubkeys", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "WithdrawnValidatorsUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ER_CHANGE_MAX_BPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETHX_ER_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_ER_UPDATE_FREQUENCY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_TRUSTED_NODES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MISSED_ATTESTATION_PENALTY_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SD_PRICE_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_STATS_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_VERIFICATION_DETAIL_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WITHDRAWN_VALIDATORS_UF", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeAddress", + "type": "address" + } + ], + "name": "addTrustedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeERInspectionMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableERInspectionMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableSafeMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableSafeMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "erChangeLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "erInspectionMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "erInspectionModeStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHXSupply", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_poolId", + "type": "uint8" + } + ], + "name": "getCurrentRewardsIndexByPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getERReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getExchangeRate", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHXSupply", + "type": "uint256" + } + ], + "internalType": "struct ExchangeRate", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_poolId", + "type": "uint8" + } + ], + "name": "getMerkleRootReportableBlockByPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMissedAttestationPenaltyReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSDPriceInETH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSDPriceReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorStats", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "exitingValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "exitedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "slashedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint32", + "name": "exitingValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "exitedValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "slashedValidatorsCount", + "type": "uint32" + } + ], + "internalType": "struct ValidatorStats", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorStatsReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorVerificationDetailReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWithdrawnValidatorReportableBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + }, + { + "internalType": "address", + "name": "_staderConfig", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "inspectionModeExchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHXSupply", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPORFeedBasedERData", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isTrustedNode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastReportedMAPDIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastReportedSDPriceData", + "outputs": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sdPriceInETH", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "lastReportingBlockNumberForValidatorVerificationDetailByPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "lastReportingBlockNumberForWithdrawnValidatorsByPoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastTrustedNodeCountChangeBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "missedAttestationPenalty", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeAddress", + "type": "address" + } + ], + "name": "removeTrustedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "safeMode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setERUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setMissedAttestationPenaltyUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setSDPriceUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setValidatorStatsUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setValidatorVerificationDetailUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_updateFrequency", + "type": "uint256" + } + ], + "name": "setWithdrawnValidatorsUpdateFrequency", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staderConfig", + "outputs": [ + { + "internalType": "contract IStaderConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "totalETHXSupply", + "type": "uint256" + } + ], + "internalType": "struct ExchangeRate", + "name": "_exchangeRate", + "type": "tuple" + } + ], + "name": "submitExchangeRateData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "sortedPubkeys", + "type": "bytes[]" + } + ], + "internalType": "struct MissedAttestationPenaltyData", + "name": "_mapd", + "type": "tuple" + } + ], + "name": "submitMissedAttestationPenalties", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sdPriceInETH", + "type": "uint256" + } + ], + "internalType": "struct SDPriceData", + "name": "_sdPriceData", + "type": "tuple" + } + ], + "name": "submitSDPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "operatorETHRewards", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "userETHRewards", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "protocolETHRewards", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "operatorSDRewards", + "type": "uint256" + } + ], + "internalType": "struct RewardsData", + "name": "_rewardsData", + "type": "tuple" + } + ], + "name": "submitSocializingRewardsMerkleRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "exitingValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "exitedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "slashedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint32", + "name": "exitingValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "exitedValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "slashedValidatorsCount", + "type": "uint32" + } + ], + "internalType": "struct ValidatorStats", + "name": "_validatorStats", + "type": "tuple" + } + ], + "name": "submitValidatorStats", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "sortedReadyToDepositPubkeys", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "sortedFrontRunPubkeys", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "sortedInvalidSignaturePubkeys", + "type": "bytes[]" + } + ], + "internalType": "struct ValidatorVerificationDetail", + "name": "_validatorVerificationDetail", + "type": "tuple" + } + ], + "name": "submitValidatorVerificationDetail", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "poolId", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "sortedPubkeys", + "type": "bytes[]" + } + ], + "internalType": "struct WithdrawnValidators", + "name": "_withdrawnValidators", + "type": "tuple" + } + ], + "name": "submitWithdrawnValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "togglePORFeedBasedERData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedNodeChangeCoolingPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedNodesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_erChangeLimit", + "type": "uint256" + } + ], + "name": "updateERChangeLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateERFromPORFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "updateFrequencyMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_staderConfig", + "type": "address" + } + ], + "name": "updateStaderConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_trustedNodeChangeCoolingPeriod", + "type": "uint256" + } + ], + "name": "updateTrustedNodeChangeCoolingPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "validatorStats", + "outputs": [ + { + "internalType": "uint256", + "name": "reportingBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "exitingValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "exitedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "slashedValidatorsBalance", + "type": "uint128" + }, + { + "internalType": "uint32", + "name": "exitingValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "exitedValidatorsCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "slashedValidatorsCount", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/index.ts b/src/dex/index.ts index 3b759aaf7..131f52b51 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -94,6 +94,7 @@ import { LitePsm } from './lite-psm/lite-psm'; import { UsualBond } from './usual-bond/usual-bond'; import { StkGHO } from './stkgho/stkgho'; import { SkyConverter } from './sky-converter/sky-converter'; +import { Stader } from './stader/stader'; const LegacyDexes = [ CurveV2, @@ -113,6 +114,7 @@ const LegacyDexes = [ ]; const Dexes = [ + Stader, Bebop, Dexalot, CurveV1, diff --git a/src/dex/stader/config.ts b/src/dex/stader/config.ts new file mode 100644 index 000000000..265c88cf6 --- /dev/null +++ b/src/dex/stader/config.ts @@ -0,0 +1,13 @@ +import { DexParams } from './types'; +import { DexConfigMap } from '../../types'; +import { Network } from '../../constants'; + +export const StaderConfig: DexConfigMap = { + Stader: { + [Network.MAINNET]: { + ETHx: '0xA35b1B31Ce002FBF2058D22F30f95D405200A15b', + SSPM: '0xcf5EA1b38380f6aF39068375516Daf40Ed70D299', + StaderOracle: '0xF64bAe65f6f2a5277571143A24FaaFDFC0C2a737', + }, + }, +}; diff --git a/src/dex/stader/stader-e2e.test.ts b/src/dex/stader/stader-e2e.test.ts new file mode 100644 index 000000000..37473da15 --- /dev/null +++ b/src/dex/stader/stader-e2e.test.ts @@ -0,0 +1,74 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; +import { ContractMethod, Network, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +describe('ETHx', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const dexKey = 'Stader'; + + const sideToContractMethods = new Map([ + [SwapSide.SELL, [ContractMethod.swapExactAmountIn]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'ETH', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + { + name: 'ETHx', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + ], + [ + { + name: 'WETH', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + { + name: 'ETHx', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL ? pair[0].sellAmount : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); +}); diff --git a/src/dex/stader/stader-events.test.ts b/src/dex/stader/stader-events.test.ts new file mode 100644 index 000000000..0c8325a16 --- /dev/null +++ b/src/dex/stader/stader-events.test.ts @@ -0,0 +1,64 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { ETHxEventPool } from './stader-pool'; +import { Network } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { ETHxPoolState } from './types'; +import { Interface, JsonFragment } from '@ethersproject/abi'; +import { StaderConfig } from './config'; +import StadeOracleAbi from '../../abi/StaderOracle.json'; + +jest.setTimeout(50 * 1000); + +async function fetchETHxPoolState( + staderPools: ETHxEventPool, + blockNumber: number, +): Promise { + return staderPools.generateState(blockNumber); +} + +describe('Stader EventPool Mainnet', function () { + const dexKey = 'Stader'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let staderPool: ETHxEventPool; + + const blockNumbers: { [eventName: string]: number[] } = { + ExchangeRateUpdated: [ + 21341230, 21334070, 21326910, 21319802, 21312600, 21305433, 21291465, + 21276861, + ], + }; + + beforeEach(async () => { + staderPool = new ETHxEventPool( + dexKey, + dexHelper, + StaderConfig[dexKey][network].StaderOracle.toLowerCase(), + new Interface(StadeOracleAbi as JsonFragment[]), + logger, + ); + }); + + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + staderPool, + staderPool.addressesSubscribed, + (_blockNumber: number) => + fetchETHxPoolState(staderPool, _blockNumber), + blockNumber, + `${dexKey}_${StaderConfig[dexKey][ + network + ].StaderOracle.toLowerCase()}`, + dexHelper.provider, + ); + }); + }); + }); +}); diff --git a/src/dex/stader/stader-integration.test.ts b/src/dex/stader/stader-integration.test.ts new file mode 100644 index 000000000..3c27bc505 --- /dev/null +++ b/src/dex/stader/stader-integration.test.ts @@ -0,0 +1,240 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { Stader } from './stader'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import { Interface, Result } from '@ethersproject/abi'; +import SSPMABI from '../../abi/SSPM.json'; + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + poolAddress: string, + amounts: bigint[], + funcName: string, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [amount]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + return BigInt(result); + }); +} + +async function checkOnChainPricing( + stader: Stader, + funcName: string, + poolAddress: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], + dexHelper: DummyDexHelper, + srcToken: string, +) { + const readerIface = new Interface(SSPMABI); + const SSPMAddress = stader.SSPM_Address; + + const readerCallData = getReaderCalldata( + SSPMAddress, + readerIface, + poolAddress, + amounts.slice(1), + funcName, + ); + + const readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +describe('Stader', function () { + const dexKey = 'Stader'; + let blockNumber: number; + let stader: Stader; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + stader = new Stader(network, dexKey, dexHelper); + if (stader.initializePricing) { + await stader.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume ETH -> ETHx SELL', async () => { + const srcTokenSymbol = 'ETH'; + const destTokenSymbol = 'ETHx'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const pools = await stader.getPoolIdentifiers( + tokens[srcTokenSymbol], + tokens[destTokenSymbol], + SwapSide.SELL, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await stader.getPricesVolume( + tokens[srcTokenSymbol], + tokens[destTokenSymbol], + amountsForSell, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsForSell, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + stader, + 'previewDeposit', + poolPrices![0].poolAddresses![0], + blockNumber, + poolPrices![0].prices, + amountsForSell, + dexHelper, + tokens[srcTokenSymbol].address, + ); + }); + + it('getPoolIdentifiers and getPricesVolume WETH -> ETHx SELL', async () => { + const srcTokenSymbol = 'WETH'; + const destTokenSymbol = 'ETHx'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const pools = await stader.getPoolIdentifiers( + tokens[srcTokenSymbol], + tokens[destTokenSymbol], + SwapSide.SELL, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await stader.getPricesVolume( + tokens[srcTokenSymbol], + tokens[destTokenSymbol], + amountsForSell, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsForSell, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + stader, + 'previewDeposit', + poolPrices![0].poolAddresses![0], + blockNumber, + poolPrices![0].prices, + amountsForSell, + dexHelper, + tokens[srcTokenSymbol].address, + ); + }); + + it('ETH getTopPoolsForToken', async function () { + const poolLiquidity = await stader.getTopPoolsForToken( + tokens['ETH'].address, + 10, + ); + console.log(`ETH Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokens['ETH'].address, dexKey); + }); + + it('WETH getTopPoolsForToken', async function () { + const poolLiquidity = await stader.getTopPoolsForToken( + tokens['WETH'].address, + 10, + ); + console.log(`WETH Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokens['WETH'].address, dexKey); + }); + + it('ETHx getTopPoolsForToken', async function () { + const poolLiquidity = await stader.getTopPoolsForToken( + tokens['ETHx'].address, + 10, + ); + console.log(`ETHx Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokens['ETHx'].address, dexKey); + }); + }); +}); diff --git a/src/dex/stader/stader-pool.ts b/src/dex/stader/stader-pool.ts new file mode 100644 index 000000000..6c8db35c2 --- /dev/null +++ b/src/dex/stader/stader-pool.ts @@ -0,0 +1,77 @@ +import { Interface } from '@ethersproject/abi'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { DeepReadonly } from 'ts-essentials'; +import { catchParseLogError } from '../../utils'; +import { ETHxPoolState } from './types'; +import { getOnChainStateETHx } from './utils'; +import { BI_POWS } from '../../bigint-constants'; + +export class ETHxEventPool extends StatefulEventSubscriber { + decoder = (log: Log) => this.poolInterface.parseLog(log); + DECIMALS = 1000000000000000000n; + addressesSubscribed: string[]; + + constructor( + parentName: string, + protected dexHelper: IDexHelper, + private poolAddress: Address, + private poolInterface: Interface, + logger: Logger, + ) { + super(parentName, 'ETHx', dexHelper, logger); + this.addressesSubscribed = [poolAddress]; + } + + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.decoder(log); + if (event.name === 'ExchangeRateUpdated') { + const totalEth = BigInt(event.args.totalEth); + const ethxSupply = BigInt(event.args.ethxSupply); + return { + totalETHBalance: totalEth, + totalETHXSupply: ethxSupply, + }; + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + async getOrGenerateState( + blockNumber: number, + ): Promise> { + let state = this.getState(blockNumber); + if (!state) { + state = await this.generateState(blockNumber); + this.setState(state, blockNumber); + } + return state; + } + + async generateState( + blockNumber: number, + ): Promise> { + const state = await getOnChainStateETHx( + this.dexHelper.multiContract, + this.poolAddress, + this.poolInterface, + blockNumber, + ); + + return state; + } + + getPrice(state: ETHxPoolState, ethAmount: bigint): bigint { + const { totalETHBalance, totalETHXSupply } = state; + + return (ethAmount * totalETHXSupply) / totalETHBalance; + } +} diff --git a/src/dex/stader/stader.ts b/src/dex/stader/stader.ts new file mode 100644 index 000000000..409ecc30f --- /dev/null +++ b/src/dex/stader/stader.ts @@ -0,0 +1,240 @@ +import { Interface, JsonFragment } from '@ethersproject/abi'; +import { NumberAsString, SwapSide } from '@paraswap/core'; +import { + AdapterExchangeParam, + Address, + DexExchangeParam, + ExchangePrices, + Logger, + PoolLiquidity, + PoolPrices, + Token, + TransferFeeParams, +} from '../../types'; +import { IDexTxBuilder } from '../idex'; +import SSPMAbi from '../../abi/SSPM.json'; +import StadeOracleAbi from '../../abi/StaderOracle.json'; +import { ETHER_ADDRESS, Network, NULL_ADDRESS } from '../../constants'; +import { IDexHelper } from '../../dex-helper'; +import { SimpleExchange } from '../simple-exchange'; +import { BI_POWS } from '../../bigint-constants'; +import { AsyncOrSync } from 'ts-essentials'; +import { ETHxEventPool } from './stader-pool'; +import { StaderData, SSPMFunctions } from './types'; +import { StaderConfig } from './config'; +import { WethFunctions } from '../weth/types'; +import ERC20ABI from '../../abi/erc20.json'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import _ from 'lodash'; +import { extractReturnAmountPosition } from '../../executor/utils'; +import { getDexKeysWithNetwork, isETHAddress } from '../../utils'; + +export class Stader + extends SimpleExchange + implements IDexTxBuilder +{ + static dexKeys = ['Stader']; + ETHxAddress: string; + SSPM_Address: string; + SSPMInterface: Interface; + StaderOracleAddress: string; + StaderOracleInterface: Interface; + erc20Interface: Interface; + needWrapNative = false; + ethxPool: ETHxEventPool; + logger: Logger; + hasConstantPriceLargeAmounts: boolean = true; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(StaderConfig, ['Stader'])); + + constructor( + protected network: Network, + dexKey: string, + dexHelper: IDexHelper, + protected config = StaderConfig[dexKey][network], + ) { + super(dexHelper, 'Stader'); + this.network = dexHelper.config.data.network; + this.ETHxAddress = this.config.ETHx.toLowerCase(); + this.SSPM_Address = this.config.SSPM.toLowerCase(); + this.SSPMInterface = new Interface(SSPMAbi as JsonFragment[]); + this.StaderOracleAddress = this.config.StaderOracle.toLowerCase(); + this.StaderOracleInterface = new Interface( + StadeOracleAbi as JsonFragment[], + ); + this.erc20Interface = new Interface(ERC20ABI); + this.logger = dexHelper.getLogger(this.dexKey); + this.ethxPool = new ETHxEventPool( + this.dexKey, + dexHelper, + this.StaderOracleAddress, + this.StaderOracleInterface, + this.logger, + ); + } + + getAdapterParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + data: StaderData, + side: SwapSide, + ): AdapterExchangeParam { + return { + targetExchange: NULL_ADDRESS, + payload: '0x', + networkFee: '0', + }; + } + + async initializePricing(blockNumber: number) { + await this.ethxPool.initialize(blockNumber); + } + + async getPricesVolume( + srcToken: Token, + destToken: Token, + amountsIn: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[] | undefined, + transferFees?: TransferFeeParams | undefined, + isFirstSwap?: boolean | undefined, + ): Promise | null> { + if (side === SwapSide.BUY) return null; + if (!this.isEligibleSwap(srcToken, destToken)) return null; + + const pool = this.ethxPool; + const state = await pool.getOrGenerateState(blockNumber); + + const unitIn = BI_POWS[18]; + const unitOut = pool.getPrice(state, unitIn); + const amountsOut = amountsIn.map(amountIn => + pool.getPrice(state, amountIn), + ); + + return [ + { + prices: amountsOut, + unit: unitOut, + data: {}, + exchange: this.dexKey, + poolIdentifier: `${ETHER_ADDRESS}_${destToken.address}`.toLowerCase(), + gasCost: 120_000, + poolAddresses: [destToken.address], + }, + ]; + } + + isEligibleSwap(srcToken: Token | string, destToken: Token | string): boolean { + const srcTokenAddress = ( + typeof srcToken === 'string' ? srcToken : srcToken.address + ).toLowerCase(); + const destTokenAddress = ( + typeof destToken === 'string' ? destToken : destToken.address + ).toLowerCase(); + + return ( + (isETHAddress(srcTokenAddress) || this.isWETH(srcTokenAddress)) && + destTokenAddress === this.ETHxAddress + ); + } + + getDexParam( + srcToken: Address, + _destToken: Address, + srcAmount: NumberAsString, + _destAmount: NumberAsString, + _recipient: Address, + _data: StaderData, + _side: SwapSide, + ): DexExchangeParam { + if (_side === SwapSide.BUY) throw new Error(`Buy not supported`); + + const swapData = this.SSPMInterface.encodeFunctionData( + SSPMFunctions.deposit, + [_recipient], + ); + + return { + needWrapNative: this.needWrapNative, + dexFuncHasRecipient: true, + exchangeData: swapData, + targetExchange: this.config.SSPM.toLowerCase(), + preSwapUnwrapCalldata: this.isWETH(srcToken) + ? this.erc20Interface.encodeFunctionData(WethFunctions.withdraw, [ + srcAmount, + ]) + : undefined, + returnAmountPos: + _side === SwapSide.SELL + ? extractReturnAmountPosition( + this.SSPMInterface, + SSPMFunctions.deposit, + ) + : undefined, + }; + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + if (side === SwapSide.BUY) return []; + + if (!this.isEligibleSwap(srcToken, destToken)) return []; + + return [`${ETHER_ADDRESS}_${destToken.address}`.toLowerCase()]; + } + + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + return CALLDATA_GAS_COST.DEX_OVERHEAD + CALLDATA_GAS_COST.LENGTH_SMALL; + } + + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return null; + } + + getTopPoolsForToken( + tokenAddress: string, + limit: number, + ): AsyncOrSync { + if (isETHAddress(tokenAddress) || this.isWETH(tokenAddress.toLowerCase())) { + return [ + { + exchange: this.dexKey, + address: this.config.ETHx, + connectorTokens: [ + { + decimals: 18, + address: this.config.ETHx, + }, + ], + liquidityUSD: 1000000000, + }, + ]; + } + + if (tokenAddress.toLowerCase() === this.ETHxAddress.toLowerCase()) { + const eth = ETHER_ADDRESS; + const weth = this.dexHelper.config.data.wrappedNativeTokenAddress; + return [eth, weth].map(t => ({ + exchange: this.dexKey, + address: this.config.ETHx, + connectorTokens: [ + { + decimals: 18, + address: t, + }, + ], + liquidityUSD: 1000000000, + })); + } + + return []; + } +} diff --git a/src/dex/stader/types.ts b/src/dex/stader/types.ts new file mode 100644 index 000000000..3dcf7b530 --- /dev/null +++ b/src/dex/stader/types.ts @@ -0,0 +1,16 @@ +export type ETHxPoolState = { + totalETHBalance: bigint; + totalETHXSupply: bigint; +}; + +export type StaderData = {}; + +export type DexParams = { + ETHx: string; + SSPM: string; + StaderOracle: string; +}; + +export enum SSPMFunctions { + deposit = 'deposit', +} diff --git a/src/dex/stader/utils.ts b/src/dex/stader/utils.ts new file mode 100644 index 000000000..4bf0f9a2b --- /dev/null +++ b/src/dex/stader/utils.ts @@ -0,0 +1,34 @@ +import { Contract } from 'web3-eth-contract'; +import { ETHxPoolState } from './types'; +import { Interface, AbiCoder } from '@ethersproject/abi'; +import { BI_POWS } from '../../bigint-constants'; + +export async function getOnChainStateETHx( + multiContract: Contract, + poolAddress: string, + poolInterface: Interface, + blockNumber: number | 'latest', +): Promise { + const coder = new AbiCoder(); + const data: { returnData: any[] } = await multiContract.methods + .aggregate([ + { + target: poolAddress, + callData: poolInterface.encodeFunctionData('getExchangeRate', []), + }, + ]) + .call({}, blockNumber); + + const decodedData = coder.decode( + ['uint256', 'uint256', 'uint256'], + data.returnData[0], + ); + + const totalETHBalance = BigInt(decodedData[1].toString()); + const totalETHXSupply = BigInt(decodedData[2].toString()); + + return { + totalETHBalance, + totalETHXSupply, + }; +} diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 258fdd5f0..29e337000 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -92,6 +92,10 @@ export const Tokens: { address: ETHER_ADDRESS, decimals: 18, }, + ETHx: { + address: '0xA35b1B31Ce002FBF2058D22F30f95D405200A15b', + decimals: 18, + }, SWETH: { address: '0xf951e335afb289353dc249e82926178eac7ded78', decimals: 18, @@ -1625,6 +1629,7 @@ export const Holders: { sUSDS: '0xd564B3aE673CAa49D054Bf185bD72a6853763eE7', SKY: '0x0ddda327A6614130CCb20bc0097313A282176A01', MKR: '0xe9aAA7A9DDc0877626C1779AbC29993aD89A6c1f', + ETHx: '0xFCC1A2c71F01B7f58Ed538a6B4AAa5A0724eB5A6', // Idle tokens AA_wstETH: '0xd7C1b48877A7dFA7D51cf1144c89C0A3F134F935', 'AA_idle_cpPOR-USDC': '0x085c8eaccA6911fE60aE3f8FbAe5F3012E3A05Ec',