Skip to content

Conversation

khoa-p
Copy link

@khoa-p khoa-p commented Jun 15, 2025

Pull Request Template: GlueX Liquidity Module Integration

Protocol Information

  • Protocol Name: Valantis
  • Protocol Website: valantis.xyz / docs.valantis.xyz
  • Indexing Smart Contract Addresses (e.g. factories):
    • N/A, just treat this as a standalone pool

Summary of Integration

Provide a brief overview of your integration:

  • What does your protocol do? The Modular DEX. Live on HyperEVM with stHYPE AMM, a next-gen pool built specific for LSTs
  • What type of liquidity does it provide (DEX, lending, yield farming, etc.)? We have built a DEX with stHYPE/HYPE as the pair. stHYPE is an LST and we lend some portion of the HYPE reserves to boost yield.
  • Any unique features that GlueX should consider? No

Implementation Details

Execution Functions Required

/**
        @notice Swap against the ALM Position in this pool.
        @param _swapParams Struct containing all params.
               * isSwapCallback If this swap should claim funds using a callback.
               * isZeroToOne Direction of the swap.
               * amountIn Input amount to swap.
               * amountOutMin Minimum output token amount required.
               * deadline Block timestamp after which the swap is no longer valid.
               * recipient Recipient address for output token.
               * swapTokenOut Address of output token.
                 If `sovereignVault != address(this)` it can be other tokens apart from token0 or token1.
               * swapContext Struct containing ALM's external, Verifier's and Swap Callback's context data.
        @return amountInUsed Amount of input token filled by this swap.
        @return amountOut Amount of output token provided by this swap.
     */
    function swap(
        SovereignPoolSwapParams calldata _swapParams
    ) external override nonReentrant returns (uint256 amountInUsed, uint256 amountOut)

ABI:

{"inputs":[{"components":[{"internalType":"bool","name":"isSwapCallback","type":"bool"},{"internalType":"bool","name":"isZeroToOne","type":"bool"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"swapTokenOut","type":"address"},{"components":[{"internalType":"bytes","name":"externalContext","type":"bytes"},{"internalType":"bytes","name":"verifierContext","type":"bytes"},{"internalType":"bytes","name":"swapCallbackContext","type":"bytes"},{"internalType":"bytes","name":"swapFeeModuleContext","type":"bytes"}],"internalType":"struct SovereignPoolSwapContextData","name":"swapContext","type":"tuple"}],"internalType":"struct SovereignPoolSwapParams","name":"_swapParams","type":"tuple"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountInUsed","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}]

At this address: 0x5365b6EF09253C7aBc0A9286eC578A9f4B413B7D

Functions Implemented

  • get_amount_out(): uses the updated logic from the Valantis stepwise fee module, solidity code is currently private
  • get_amount_in(): same as the above
  • get_apy(): pulled directly from the Valantis backend
  • get_tvl(): Gets reserves of stHYPE and HYPE, returns the sum minus any tokens pending LP withdrawal

Dynamic States Required for AMM Calculations

Specify any on-chain values that change frequently and are required for accurate AMM computations, such as:

  • Current reserves
  • Current prices
  • Pending liquidity changes
  • Other time-sensitive variables

Pool states:

  • Lens address: 0x68675DC8406252b6950128f6504A5E287Ef24ED0
  • STEX AMM: 0x39694eFF3b02248929120c73F90347013Aec834d
  • Fee module: 0x75d85d081E189F72d5C189e94d1c2cc0026AFB70
  • Withdrawal module: 0x69e487aA3132708d08a979b2d07c5119Bb77F698

For pool reserves state, use the lens contract with the STEX address as input

reserves_token_0
reserves_token_1
amount_0_pending_unstaking
amount_1_pending_lp_withdrawal
amount_1_lending_pool

ABI:

{"type":"function","name":"getAllReserves","inputs":[{"name":"stex","type":"address","internalType":"address"}],"outputs":[{"name":"reserve0Pool","type":"uint256","internalType":"uint256"},{"name":"reserve0Unstaking","type":"uint256","internalType":"uint256"},{"name":"reserve1Pool","type":"uint256","internalType":"uint256"},{"name":"reserve1Lending","type":"uint256","internalType":"uint256"},{"name":"amount1PendingLPWithdrawal","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}

getAllReserves(0x39694eFF3b02248929120c73F90347013Aec834d) at lens address

For fee parameters:

Contract address: 0x75d85d081E189F72d5C189e94d1c2cc0026AFB70

ABI:

[{"type":"constructor","inputs":[{"name":"_owner","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"getSwapFeeInBips","inputs":[{"name":"_tokenIn","type":"address","internalType":"address"},{"name":"","type":"address","internalType":"address"},{"name":"_amountIn","type":"uint256","internalType":"uint256"},{"name":"","type":"address","internalType":"address"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"swapFeeModuleData","type":"tuple","internalType":"struct SwapFeeModuleData","components":[{"name":"feeInBips","type":"uint256","internalType":"uint256"},{"name":"internalContext","type":"bytes","internalType":"bytes"}]}],"stateMutability":"view"},{"type":"function","name":"getToken0FeeInBips","inputs":[],"outputs":[{"name":"","type":"uint32[]","internalType":"uint32[]"}],"stateMutability":"view"},{"type":"function","name":"maxThresholdToken1","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"minThresholdToken1","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"numStepsToken0FeeCurve","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pool","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setFeeParamsToken0","inputs":[{"name":"_minThresholdToken1","type":"uint256","internalType":"uint256"},{"name":"_maxThresholdToken1","type":"uint256","internalType":"uint256"},{"name":"_feeStepsInBips","type":"uint32[]","internalType":"uint32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPool","inputs":[{"name":"_pool","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"FeeParamsSetToken0","inputs":[{"name":"maxThresholdToken1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"minThresholdToken1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"numStepsToken1","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"PoolSet","inputs":[{"name":"pool","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"StepwiseFeeModule__ZeroAddress","inputs":[]},{"type":"error","name":"StepwiseFeeModule__getSwapFeeInBips_InvalidMaxToken1Threshold","inputs":[]},{"type":"error","name":"StepwiseFeeModule__getSwapFeeInBips_InvalidMinToken1Threshold","inputs":[]},{"type":"error","name":"StepwiseFeeModule__getSwapFeeInBips_InvalidToken1Threshold","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__FeeStepsNotMonotonicallyNonDecreasing","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__FeeTooHigh","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__FeeTooLow","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__MaxToken1ThresholdZero","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__MinToken1ThresholdAboveMaxToken1Threshold","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__MinToken1ThresholdZero","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setFeeParamsToken0__ZeroSteps","inputs":[]},{"type":"error","name":"StepwiseFeeModule__setPool_AlreadySet","inputs":[]}]

Pool states you'll need from this:

  • fee_stepwise_in_bips: Use getToken0FeeInBips()
  • min_threshold_token_1: Use minThresholdToken1()
  • max_threshold_token_1: Use maxThresholdToken1()
  • num_steps_token_0_fee_curve: Use numStepsToken0FeeCurve()

Withdrawal module, address: 0x69e487aA3132708d08a979b2d07c5119Bb77F698

ABI:

[{"type":"constructor","inputs":[{"name":"_overseer","type":"address","internalType":"address"},{"name":"_owner","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"receive","stateMutability":"payable"},{"type":"function","name":"LPWithdrawals","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"recipient","type":"address","internalType":"address"},{"name":"amountToken1","type":"uint96","internalType":"uint96"},{"name":"cumulativeAmountToken1LPWithdrawalCheckpoint","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken0PendingUnstaking","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken0PendingUnstakingBeforeUpdate","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken1ClaimableLPWithdrawal","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken1LendingPool","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken1PendingLPWithdrawal","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"amountToken1PendingLPWithdrawalBeforeUpdate","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"burnToken0AfterWithdraw","inputs":[{"name":"_amountToken0","type":"uint256","internalType":"uint256"},{"name":"_recipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cancelLendingModuleProposal","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claim","inputs":[{"name":"_idLPQueue","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"convertToToken0","inputs":[{"name":"_amountToken1","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"convertToToken1","inputs":[{"name":"_amountToken0","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"cumulativeAmountToken1ClaimableLPWithdrawal","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"cumulativeAmountToken1LPWithdrawal","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getLPWithdrawals","inputs":[{"name":"_idLPWithdrawal","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct LPWithdrawalRequest","components":[{"name":"recipient","type":"address","internalType":"address"},{"name":"amountToken1","type":"uint96","internalType":"uint96"},{"name":"cumulativeAmountToken1LPWithdrawalCheckpoint","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"idLPWithdrawal","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"isLocked","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"lendingModule","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ILendingModule"}],"stateMutability":"view"},{"type":"function","name":"lendingModuleProposal","inputs":[],"outputs":[{"name":"lendingModule","type":"address","internalType":"address"},{"name":"startTimestamp","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"overseer","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pool","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"proposeLendingModule","inputs":[{"name":"_lendingModule","type":"address","internalType":"address"},{"name":"_timelockDelay","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setProposedLendingModule","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setSTEX","inputs":[{"name":"_stex","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stakeToken1","inputs":[{"name":"_amountToken1","type":"uint256","internalType":"uint256"},{"name":"_communityCode","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stex","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"supplyToken1ToLendingPool","inputs":[{"name":"_amountToken1","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"sweep","inputs":[{"name":"_token","type":"address","internalType":"address"},{"name":"_recipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"token0BalanceToShares","inputs":[{"name":"_balance","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"token0SharesOf","inputs":[{"name":"_account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"token0SharesToBalance","inputs":[{"name":"_shares","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unstakeToken0Reserves","inputs":[{"name":"_unstakeAmountToken0","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"update","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"withdrawToken1FromLendingPool","inputs":[{"name":"_amountToken1","type":"uint256","internalType":"uint256"},{"name":"_recipient","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"AmountSuppliedToLendingModule","inputs":[{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AmountToken0Unstaked","inputs":[{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AmountToken1Staked","inputs":[{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"AmountWithdrawnFromLendingModule","inputs":[{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"LPWithdrawalRequestClaimed","inputs":[{"name":"id","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"LPWithdrawalRequestCreated","inputs":[{"name":"id","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amountToken1","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"recipient","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"LendingModuleProposalCancelled","inputs":[],"anonymous":false},{"type":"event","name":"LendingModuleProposed","inputs":[{"name":"lendingModule","type":"address","indexed":false,"internalType":"address"},{"name":"startTimestamp","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"LendingModuleSet","inputs":[{"name":"lendingModule","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"STEXSet","inputs":[{"name":"stex","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Sweep","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"recipient","type":"address","indexed":true,"internalType":"address"},{"name":"balance","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Update","inputs":[],"anonymous":false},{"type":"error","name":"FailedCall","inputs":[]},{"type":"error","name":"InsufficientBalance","inputs":[{"name":"balance","type":"uint256","internalType":"uint256"},{"name":"needed","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"stHYPEWithdrawalModule__OnlySTEX","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__OnlySTEXOrOwner","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__PoolNonReentrant","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__ZeroAddress","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule___verifyTimelockDelay_TimelockTooHigh","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule___verifyTimelockDelay_TimelockTooLow","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__claim_AlreadyClaimed","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__claim_CannotYetClaim","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__claim_InsufficientAmountToClaim","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__proposeLendingModule_ProposalAlreadyActive","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__setProposedLendingModule_InactiveProposal","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__setProposedLendingModule_ProposalNotActive","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__setSTEX_AlreadySet","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__sweep_Token0CannotBeSweeped","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__sweep_Token1CannotBeSweeped","inputs":[]},{"type":"error","name":"stHYPEWithdrawalModule__withdrawToken1FromLendingPool_InsufficientAmountWithdrawn","inputs":[]}]

State that you'll need from this:

exchange_rate_to_token_0: Call convert_to_token_0(1 ether)
exchange_rate_to_token_1: Call convert_to_token_1(1 ether)

Static States Required for AMM Calculations

Specify any on-chain values that remain constant such as:

token0/token1:

ABI:

token0:

{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}

token1:

{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}

Note: We support swaps from HYPE/wHYPE -> stHYPE

Dependencies

For APY, you will have a dependency on analytics-v3.valantis-analytics.xyz. I'll get y'all the API token for this

Other Requirements

  • API Keys: We can speak privately about this
  • Special Access Requirements: N/A

Test Results

Provide details of tests performed, including:

> pytest --cov=modules --cov-report=html tests/test_valantis_stex_liquidity_module.py -s
======================================================================================================= test session starts ========================================================================================================
platform darwin -- Python 3.10.0, pytest-8.0.0, pluggy-1.5.0
rootdir: /Users/khoa/valantis/liquidity-module-self-integration
plugins: cov-4.1.0, mock-3.12.0
collected 8 items                                                                                                                                                                                                                  

tests/test_valantis_stex_liquidity_module.py ........

---------- coverage: platform darwin, python 3.10.0-final-0 ----------
Coverage HTML written to dir htmlcov


======================================================================================================== 8 passed in 0.53s =======
  • Tested getAmountOut and getAmountIn with some inputs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant