diff --git a/pkg/liquidity-source/beets-ss/abis.go b/pkg/liquidity-source/beets-ss/abis.go new file mode 100644 index 000000000..cf93f4a39 --- /dev/null +++ b/pkg/liquidity-source/beets-ss/abis.go @@ -0,0 +1,30 @@ +package beets_ss + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/accounts/abi" +) + +var ( + sonicStakingABI abi.ABI +) + +func init() { + builder := []struct { + ABI *abi.ABI + data []byte + }{ + { + &sonicStakingABI, sonicStakingABIJson, + }, + } + + for _, b := range builder { + var err error + *b.ABI, err = abi.JSON(bytes.NewReader(b.data)) + if err != nil { + panic(err) + } + } +} diff --git a/pkg/liquidity-source/beets-ss/abis/SonicStaking.json b/pkg/liquidity-source/beets-ss/abis/SonicStaking.json new file mode 100644 index 000000000..5d8bcee2f --- /dev/null +++ b/pkg/liquidity-source/beets-ss/abis/SonicStaking.json @@ -0,0 +1,2319 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DelegateAmountCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "DepositPaused", + "type": "error" + }, + { + "inputs": [], + "name": "DepositTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "DonationAmountCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "DonationAmountTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NativeTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + } + ], + "name": "NoDelegationForValidator", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "PausedValueDidNotChange", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolFeeTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolFeeTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RewardsClaimedTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "SFCAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "SenderNotSFC", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "refundRatio", + "type": "uint256" + } + ], + "name": "SfcSlashMustBeAccepted", + "type": "error" + }, + { + "inputs": [], + "name": "TreasuryAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "name": "UnauthorizedWithdraw", + "type": "error" + }, + { + "inputs": [], + "name": "UndelegateAmountCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + } + ], + "name": "UndelegateAmountExceedsDelegated", + "type": "error" + }, + { + "inputs": [], + "name": "UndelegateAmountExceedsPool", + "type": "error" + }, + { + "inputs": [], + "name": "UndelegateAmountTooSmall", + "type": "error" + }, + { + "inputs": [], + "name": "UndelegateFromPoolPaused", + "type": "error" + }, + { + "inputs": [], + "name": "UndelegatePaused", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedWithdrawKind", + "type": "error" + }, + { + "inputs": [], + "name": "UserWithdrawsMaxSizeCannotBeZero", + "type": "error" + }, + { + "inputs": [], + "name": "UserWithdrawsSkipTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "name": "WithdrawAlreadyProcessed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "name": "WithdrawDelayNotElapsed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "name": "WithdrawIdDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "WithdrawsPaused", + "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": true, + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + } + ], + "name": "Delegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "DepositPausedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountShares", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + } + ], + "name": "Donated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssetsWithdrawn", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "emergency", + "type": "bool" + } + ], + "name": "OperatorClawBackExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + } + ], + "name": "OperatorClawBackInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newFeeBIPS", + "type": "uint256" + } + ], + "name": "ProtocolFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountClaimed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "protocolFee", + "type": "uint256" + } + ], + "name": "RewardsClaimed", + "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": "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": "newTreasury", + "type": "address" + } + ], + "name": "TreasuryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "UndelegateFromPoolPausedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "UndelegatePausedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum SonicStaking.WithdrawKind", + "name": "kind", + "type": "uint8" + } + ], + "name": "Undelegated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "WithdrawDelaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "WithdrawPausedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum SonicStaking.WithdrawKind", + "name": "kind", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "emergency", + "type": "bool" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [], + "name": "CLAIM_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PROTOCOL_FEE_BIPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_CLAIM_REWARDS_AMOUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_DEPOSIT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_DONATION_AMOUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_UNDELEGATE_AMOUNT_SHARES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPERATOR_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SFC", + "outputs": [ + { + "internalType": "contract ISFC", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "validatorIds", + "type": "uint256[]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sharesAmount", + "type": "uint256" + } + ], + "name": "convertToAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "assetAmount", + "type": "uint256" + } + ], + "name": "convertToShares", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "donate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRate", + "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": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "skip", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSize", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "reverseOrder", + "type": "bool" + } + ], + "name": "getUserWithdraws", + "outputs": [ + { + "components": [ + { + "internalType": "enum SonicStaking.WithdrawKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isWithdrawn", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "internalType": "struct SonicStaking.WithdrawRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "name": "getWithdrawRequest", + "outputs": [ + { + "components": [ + { + "internalType": "enum SonicStaking.WithdrawKind", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "assetAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isWithdrawn", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "internalType": "struct SonicStaking.WithdrawRequest", + "name": "", + "type": "tuple" + } + ], + "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": "contract ISFC", + "name": "_sfc", + "type": "address" + }, + { + "internalType": "address", + "name": "_treasury", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "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": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "emergency", + "type": "bool" + } + ], + "name": "operatorExecuteClawBack", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAssets", + "type": "uint256" + } + ], + "name": "operatorInitiateClawBack", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualAmountUndelegated", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingClawBackAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": "protocolFeeBIPS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "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": [ + { + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "setDepositPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFeeBIPS", + "type": "uint256" + } + ], + "name": "setProtocolFeeBIPS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTreasury", + "type": "address" + } + ], + "name": "setTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "setUndelegateFromPoolPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "setUndelegatePaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "delay", + "type": "uint256" + } + ], + "name": "setWithdrawDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newValue", + "type": "bool" + } + ], + "name": "setWithdrawPaused", + "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": "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": "totalDelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalPool", + "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": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasury", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validatorId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountShares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountShares", + "type": "uint256" + } + ], + "name": "undelegateFromPool", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "undelegateFromPoolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "validatorIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amountShares", + "type": "uint256[]" + } + ], + "name": "undelegateMany", + "outputs": [ + { + "internalType": "uint256[]", + "name": "withdrawIds", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "undelegatePaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userNumWithdraws", + "outputs": [ + { + "internalType": "uint256", + "name": "numWithdraws", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "userWithdraws", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "emergency", + "type": "bool" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "withdrawIds", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "emergency", + "type": "bool" + } + ], + "name": "withdrawMany", + "outputs": [ + { + "internalType": "uint256[]", + "name": "amountsWithdrawn", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] \ No newline at end of file diff --git a/pkg/liquidity-source/beets-ss/config.go b/pkg/liquidity-source/beets-ss/config.go new file mode 100644 index 000000000..f796217ea --- /dev/null +++ b/pkg/liquidity-source/beets-ss/config.go @@ -0,0 +1,6 @@ +package beets_ss + +type Config struct { + ChainID string `json:"chainID"` + PoolAddress string `json:"pool_address"` +} diff --git a/pkg/liquidity-source/beets-ss/constant.go b/pkg/liquidity-source/beets-ss/constant.go new file mode 100644 index 000000000..cc2e20b26 --- /dev/null +++ b/pkg/liquidity-source/beets-ss/constant.go @@ -0,0 +1,24 @@ +package beets_ss + +import ( + "math/big" + + "github.com/holiman/uint256" +) + +const ( + DexType = "beets-ss" + Beets_Staked_Sonic_Address = "0xe5da20f15420ad15de0fa650600afc998bbe3955" + defaultReserve = "100000000000000000000000000" +) + +var ( + defaultGas = Gas{Swap: 60000} + + MIN_DEPOSIT = uint256.NewInt(1e16) + ZERO = big.NewInt(0) + + methodTotalSupply = "totalSupply" + methodTotalAssets = "totalAssets" + methodDepositPaused = "depositPaused" +) diff --git a/pkg/liquidity-source/beets-ss/embed.go b/pkg/liquidity-source/beets-ss/embed.go new file mode 100644 index 000000000..ebd7473fc --- /dev/null +++ b/pkg/liquidity-source/beets-ss/embed.go @@ -0,0 +1,6 @@ +package beets_ss + +import _ "embed" + +//go:embed abis/SonicStaking.json +var sonicStakingABIJson []byte diff --git a/pkg/liquidity-source/beets-ss/pool_list_updater.go b/pkg/liquidity-source/beets-ss/pool_list_updater.go new file mode 100644 index 000000000..86acffe6c --- /dev/null +++ b/pkg/liquidity-source/beets-ss/pool_list_updater.go @@ -0,0 +1,75 @@ +package beets_ss + +import ( + "context" + "strings" + "time" + + "github.com/KyberNetwork/ethrpc" + "github.com/KyberNetwork/logger" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/valueobject" +) + +type ( + PoolsListUpdater struct { + config *Config + ethrpcClient *ethrpc.Client + hasInitialized bool + } +) + +func NewPoolsListUpdater( + cfg *Config, + ethrpcClient *ethrpc.Client, +) *PoolsListUpdater { + return &PoolsListUpdater{ + config: cfg, + ethrpcClient: ethrpcClient, + } +} + +func (u *PoolsListUpdater) GetNewPools(ctx context.Context, metadataBytes []byte) ([]entity.Pool, []byte, error) { + if u.hasInitialized { + logger.Debug("skip since pool has been initialized") + return nil, nil, nil + } + + pools, err := u.initPool() + if err != nil { + return nil, metadataBytes, err + } + + u.hasInitialized = true + + return pools, metadataBytes, nil +} + +func (u *PoolsListUpdater) initPool() ([]entity.Pool, error) { + return []entity.Pool{ + { + Address: Beets_Staked_Sonic_Address, + Exchange: string(valueobject.ExchangeBeetsSS), + Type: DexType, + Timestamp: time.Now().Unix(), + Reserves: entity.PoolReserves{defaultReserve, defaultReserve}, + Tokens: []*entity.PoolToken{ + { + Address: strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic]), + Name: "Wrapped Sonic", + Symbol: "wS", + Decimals: 18, + Swappable: true, + }, + { + Address: Beets_Staked_Sonic_Address, + Name: "Beets Staked Sonic", + Symbol: "stS", + Decimals: 18, + Swappable: true, + }, + }, + }, + }, nil +} diff --git a/pkg/liquidity-source/beets-ss/pool_simulator.go b/pkg/liquidity-source/beets-ss/pool_simulator.go new file mode 100644 index 000000000..bb34c2769 --- /dev/null +++ b/pkg/liquidity-source/beets-ss/pool_simulator.go @@ -0,0 +1,169 @@ +package beets_ss + +import ( + "errors" + "math/big" + "strings" + + "github.com/KyberNetwork/blockchain-toolkit/integer" + "github.com/KyberNetwork/blockchain-toolkit/number" + "github.com/goccy/go-json" + "github.com/holiman/uint256" + "github.com/samber/lo" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + poolpkg "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" + utils "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/valueobject" +) + +var ( + ErrInvalidToken = errors.New("invalid token") + ErrInvalidReserve = errors.New("invalid reserve") + ErrInvalidAmountIn = errors.New("invalid amount in") + ErrInsufficientInputAmount = errors.New("INSUFFICIENT_INPUT_AMOUNT") + + ErrDepositTooSmall = errors.New("deposit too small") + ErrDepositPaused = errors.New("deposit paused") + ErrOverflow = errors.New("overflow") +) + +type ( + PoolSimulator struct { + poolpkg.Pool + + totalSupply *uint256.Int + totalAssets *uint256.Int + depositPaused bool + + gas Gas + } + + Gas struct { + Swap int64 + } +) + +func NewPoolSimulator(entityPool entity.Pool) (*PoolSimulator, error) { + var extra Extra + if err := json.Unmarshal([]byte(entityPool.Extra), &extra); err != nil { + return nil, err + } + + totalAssets, overflow := uint256.FromBig(extra.TotalAssets) + if overflow { + return nil, ErrOverflow + } + + totalSupply, overflow := uint256.FromBig(extra.TotalSupply) + if overflow { + return nil, ErrOverflow + } + + return &PoolSimulator{ + Pool: poolpkg.Pool{Info: poolpkg.PoolInfo{ + Address: entityPool.Address, + ReserveUsd: entityPool.ReserveUsd, + Exchange: entityPool.Exchange, + Type: entityPool.Type, + Tokens: lo.Map(entityPool.Tokens, func(item *entity.PoolToken, index int) string { return item.Address }), + Reserves: lo.Map(entityPool.Reserves, func(item string, index int) *big.Int { return utils.NewBig(item) }), + BlockNumber: entityPool.BlockNumber, + }}, + totalAssets: totalAssets, + totalSupply: totalSupply, + depositPaused: extra.DepositPaused, + + gas: defaultGas, + }, nil +} + +func (s *PoolSimulator) CalcAmountOut(param poolpkg.CalcAmountOutParams) (*poolpkg.CalcAmountOutResult, error) { + var ( + tokenAmountIn = param.TokenAmountIn + tokenOut = param.TokenOut + ) + + indexIn, indexOut := s.GetTokenIndex(tokenAmountIn.Token), s.GetTokenIndex(tokenOut) + if indexIn < 0 || indexOut < 0 { + return nil, ErrInvalidToken + } + + amountIn, overflow := uint256.FromBig(tokenAmountIn.Amount) + if overflow { + return nil, ErrInvalidAmountIn + } + + if amountIn.Cmp(number.Zero) <= 0 { + return nil, ErrInsufficientInputAmount + } + + amountOut, err := s.deposit(amountIn) + if err != nil { + return nil, err + } + + return &poolpkg.CalcAmountOutResult{ + TokenAmountOut: &poolpkg.TokenAmount{Token: s.Pool.Info.Tokens[indexOut], Amount: amountOut.ToBig()}, + Fee: &poolpkg.TokenAmount{Token: s.Pool.Info.Tokens[indexIn], Amount: integer.Zero()}, + Gas: s.gas.Swap, + }, nil +} + +func (s *PoolSimulator) deposit(amountIn *uint256.Int) (*uint256.Int, error) { + if amountIn.Cmp(MIN_DEPOSIT) < 0 { + return nil, ErrDepositTooSmall + } + + if s.depositPaused { + return nil, ErrDepositPaused + } + + sharesAmount := s.convertToShares(amountIn) + + return sharesAmount, nil +} + +func (s *PoolSimulator) convertToShares(assetAmount *uint256.Int) *uint256.Int { + if s.totalAssets.IsZero() || s.totalSupply.IsZero() { + return assetAmount + } + + return new(uint256.Int).Div( + new(uint256.Int).Mul(assetAmount, s.totalSupply), + s.totalAssets, + ) +} + +func (s *PoolSimulator) UpdateBalance(params poolpkg.UpdateBalanceParams) { + indexIn, indexOut := s.GetTokenIndex(params.TokenAmountIn.Token), s.GetTokenIndex(params.TokenAmountOut.Token) + if indexIn < 0 || indexOut < 0 { + return + } + + s.Pool.Info.Reserves[indexIn] = new(big.Int).Add(s.Pool.Info.Reserves[indexIn], params.TokenAmountIn.Amount) + s.Pool.Info.Reserves[indexOut] = new(big.Int).Sub(s.Pool.Info.Reserves[indexOut], params.TokenAmountOut.Amount) + + s.totalAssets = new(uint256.Int).Add(s.totalAssets, uint256.MustFromBig(params.TokenAmountIn.Amount)) + s.totalSupply = new(uint256.Int).Add(s.totalSupply, uint256.MustFromBig(params.TokenAmountOut.Amount)) +} + +func (s *PoolSimulator) CanSwapTo(token string) []string { + if strings.EqualFold(token, Beets_Staked_Sonic_Address) { + return []string{strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic])} + } + return []string{} +} + +func (s *PoolSimulator) CanSwapFrom(token string) []string { + if strings.EqualFold(token, valueobject.WrappedNativeMap[valueobject.ChainIDSonic]) { + return []string{Beets_Staked_Sonic_Address} + } + return []string{} +} + +func (s *PoolSimulator) GetMetaInfo(_ string, _ string) interface{} { + return PoolMeta{ + BlockNumber: s.Pool.Info.BlockNumber, + } +} diff --git a/pkg/liquidity-source/beets-ss/pool_simulator_test.go b/pkg/liquidity-source/beets-ss/pool_simulator_test.go new file mode 100644 index 000000000..7e3bb03ca --- /dev/null +++ b/pkg/liquidity-source/beets-ss/pool_simulator_test.go @@ -0,0 +1,85 @@ +package beets_ss + +import ( + "math/big" + "strings" + "testing" + + poolpkg "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" + utils "github.com/KyberNetwork/kyberswap-dex-lib/pkg/util/bignumber" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/valueobject" + "github.com/stretchr/testify/assert" +) + +func TestPoolSimulator_CalcAmountOut(t *testing.T) { + testCases := []struct { + name string + poolSimulator PoolSimulator + tokenAmountIn poolpkg.TokenAmount + tokenOut string + expectedAmountOut *big.Int + expectedError error + }{ + { + name: "Swap from wS to stS successfully", + poolSimulator: PoolSimulator{ + Pool: poolpkg.Pool{ + Info: poolpkg.PoolInfo{ + Address: Beets_Staked_Sonic_Address, + Tokens: []string{Beets_Staked_Sonic_Address, strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic])}, + Reserves: []*big.Int{utils.NewBig(defaultReserve), utils.NewBig(defaultReserve)}, + }, + }, + totalSupply: utils.NewUint256("55239936004195121896978015"), + totalAssets: utils.NewUint256("55319744731539794782367353"), + }, + tokenAmountIn: poolpkg.TokenAmount{ + Amount: big.NewInt(1e18), + Token: strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic]), + }, + tokenOut: Beets_Staked_Sonic_Address, + expectedAmountOut: utils.NewBig("998557319312806390"), + expectedError: nil, + }, + { + name: "Swap from wS to stS with zero assets", + poolSimulator: PoolSimulator{ + Pool: poolpkg.Pool{ + Info: poolpkg.PoolInfo{ + Address: Beets_Staked_Sonic_Address, + Tokens: []string{Beets_Staked_Sonic_Address, strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic])}, + Reserves: []*big.Int{utils.NewBig(defaultReserve), utils.NewBig(defaultReserve)}, + }, + }, + totalSupply: utils.NewUint256("0"), + totalAssets: utils.NewUint256("0"), + }, + tokenAmountIn: poolpkg.TokenAmount{ + Amount: utils.NewBig(defaultReserve), + Token: strings.ToLower(valueobject.WrappedNativeMap[valueobject.ChainIDSonic]), + }, + tokenOut: Beets_Staked_Sonic_Address, + expectedAmountOut: utils.NewBig(defaultReserve), + expectedError: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.poolSimulator.CanSwapFrom(tc.tokenAmountIn.Token), []string{Beets_Staked_Sonic_Address}) + assert.Equal(t, tc.poolSimulator.CanSwapFrom(tc.tokenOut), []string{}) + + result, err := tc.poolSimulator.CalcAmountOut(poolpkg.CalcAmountOutParams{ + TokenAmountIn: tc.tokenAmountIn, + TokenOut: tc.tokenOut, + Limit: nil, + }) + + if tc.expectedError != nil { + assert.ErrorIs(t, tc.expectedError, err) + } else { + assert.Equal(t, tc.expectedAmountOut, result.TokenAmountOut.Amount) + } + }) + } +} diff --git a/pkg/liquidity-source/beets-ss/pool_tracker.go b/pkg/liquidity-source/beets-ss/pool_tracker.go new file mode 100644 index 000000000..c440c41eb --- /dev/null +++ b/pkg/liquidity-source/beets-ss/pool_tracker.go @@ -0,0 +1,96 @@ +package beets_ss + +import ( + "context" + "math/big" + "time" + + "github.com/KyberNetwork/ethrpc" + "github.com/goccy/go-json" + + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/entity" + "github.com/KyberNetwork/kyberswap-dex-lib/pkg/source/pool" +) + +type PoolTracker struct { + config *Config + ethrpcClient *ethrpc.Client +} + +func NewPoolTracker( + config *Config, + ethrpcClient *ethrpc.Client, +) (*PoolTracker, error) { + return &PoolTracker{ + config: config, + ethrpcClient: ethrpcClient, + }, nil +} + +func (d *PoolTracker) GetNewPoolState( + ctx context.Context, + p entity.Pool, + params pool.GetNewPoolStateParams, +) (entity.Pool, error) { + blocknumber, totalAssets, totalSupply, depositPaused, err := d.getPoolData(ctx) + if err != nil { + return p, err + } + + return d.updatePool(p, blocknumber, totalAssets, totalSupply, depositPaused) +} + +func (d *PoolTracker) updatePool(pool entity.Pool, blocknumber, totalAssets, totalSupply *big.Int, depositPaused bool) (entity.Pool, error) { + extra := Extra{ + TotalAssets: totalAssets, + TotalSupply: totalSupply, + DepositPaused: depositPaused, + } + + extraBytes, err := json.Marshal(extra) + if err != nil { + return pool, err + } + + pool.Extra = string(extraBytes) + pool.BlockNumber = blocknumber.Uint64() + pool.Timestamp = time.Now().Unix() + + return pool, nil +} + +func (d *PoolTracker) getPoolData(ctx context.Context) (*big.Int, *big.Int, *big.Int, bool, error) { + req := d.ethrpcClient.NewRequest().SetContext(ctx) + + var ( + totalAssets = ZERO + totalSupply = ZERO + depositPaused bool + ) + + req.AddCall(ðrpc.Call{ + ABI: sonicStakingABI, + Target: Beets_Staked_Sonic_Address, + Method: methodTotalAssets, + Params: nil, + }, []interface{}{&totalAssets}) + req.AddCall(ðrpc.Call{ + ABI: sonicStakingABI, + Target: Beets_Staked_Sonic_Address, + Method: methodTotalSupply, + Params: nil, + }, []interface{}{&totalSupply}) + req.AddCall(ðrpc.Call{ + ABI: sonicStakingABI, + Target: Beets_Staked_Sonic_Address, + Method: methodDepositPaused, + Params: nil, + }, []interface{}{&depositPaused}) + + resp, err := req.Aggregate() + if err != nil { + return nil, nil, nil, false, err + } + + return resp.BlockNumber, totalAssets, totalSupply, depositPaused, nil +} diff --git a/pkg/liquidity-source/beets-ss/types.go b/pkg/liquidity-source/beets-ss/types.go new file mode 100644 index 000000000..0c5b283f8 --- /dev/null +++ b/pkg/liquidity-source/beets-ss/types.go @@ -0,0 +1,13 @@ +package beets_ss + +import "math/big" + +type Extra struct { + TotalSupply *big.Int `json:"total_supply"` + TotalAssets *big.Int `json:"total_asset"` + DepositPaused bool `json:"deposit_paused"` +} + +type PoolMeta struct { + BlockNumber uint64 `json:"blockNumber"` +} diff --git a/pkg/pooltypes/pooltypes.go b/pkg/pooltypes/pooltypes.go index c48fd6c10..c180531ad 100644 --- a/pkg/pooltypes/pooltypes.go +++ b/pkg/pooltypes/pooltypes.go @@ -10,6 +10,7 @@ import ( bancorv3 "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bancor-v3" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bebop" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/bedrock/unieth" + beetsss "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/beets-ss" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/clipper" "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/plain" curveStableMetaNg "github.com/KyberNetwork/kyberswap-dex-lib/pkg/liquidity-source/curve/stable-meta-ng" @@ -271,6 +272,7 @@ type Types struct { MxTrading string LO1inch string VirtualFun string + BeetsSS string } var ( @@ -414,5 +416,6 @@ var ( MxTrading: mxtrading.DexType, LO1inch: lo1inch.DexType, VirtualFun: virtualfun.DexType, + BeetsSS: beetsss.DexType, } ) diff --git a/pkg/valueobject/exchange.go b/pkg/valueobject/exchange.go index 0a9376a0b..12bba74ea 100644 --- a/pkg/valueobject/exchange.go +++ b/pkg/valueobject/exchange.go @@ -387,6 +387,7 @@ var ( ExchangeMetropolisLB Exchange = "metropolis-lb" ExchangeSonicMarket Exchange = "sonic-market" ExchangeSboom Exchange = "sboom" + ExchangeBeetsSS Exchange = "beets-ss" ) var AMMSourceSet = map[Exchange]struct{}{ @@ -706,6 +707,7 @@ var AMMSourceSet = map[Exchange]struct{}{ ExchangeMetropolisLB: {}, ExchangeSonicMarket: {}, ExchangeSboom: {}, + ExchangeBeetsSS: {}, } func IsAMMSource(exchange Exchange) bool {