Skip to content

feat(range-pool): add Range Pool executor adapter - #10

Open
alf1303 wants to merge 2 commits into
KyberNetwork:mainfrom
alf1303:range-pool-adapter
Open

feat(range-pool): add Range Pool executor adapter#10
alf1303 wants to merge 2 commits into
KyberNetwork:mainfrom
alf1303:range-pool-adapter

Conversation

@alf1303

@alf1303 alf1303 commented Aug 17, 2026

Copy link
Copy Markdown

feat(range-pool): add Range Pool executor adapter

Background

Range Pools are a concentrated-liquidity, Balancer-V3-shaped DEX on Ethereum mainnet, running on a custom, non-canonical Balancer V3 Vault 0x955244EDC797A1C1b04134b600f819aC23C76081. The off-chain pricing connector is a companion PR to KyberNetwork/kyberswap-dex-lib: KyberNetwork/kyberswap-dex-lib#1612.

What this adds

src/adapters/range-pool/RangePoolAdapter.solexecuteRangePool(bytes data, uint256 amountIn, address tokenIn, address tokenOut, address recipient).

A Balancer-V3 pool has no direct swap entrypoint; swaps go through the Vault's transient-accounting flow. The adapter settles Vault-direct (no Router, no Permit2):

  1. Vault.unlock(callback)
  2. inside the Vault-guarded callback: swap(EXACT_IN) → pay input (transfer tokenIn to Vault + settle) → sendTo(tokenOut, recipient)
  3. return amountOut

EXACT_IN only (aggregator settlement). Native ETH is wrapped/unwrapped at the edges since the Vault only handles WETH. Vendored minimal interfaces IRangeVault.sol / IWETH.sol (structs/enums copied verbatim from the Vault source, not guessed).

Testing

test/adapters/range-pool/RangePoolAdapter.t.sol — Foundry mainnet-fork parity: for both live pools (ROME/USDT 0xaf037e…b36, 8-token 0x67c02f…f29b, WETH idx 6), realized output == Router.querySwapSingleTokenExactIn to the wei, plus native-ETH in/out, the OnlyVault callback guard, and minimum-trade error symmetry. forge build / forge fmt clean.

Run: forge test --match-path 'test/adapters/range-pool/*' --fork-url <mainnet RPC>

Note

Funding uses forge-std deal (self-verifying); no hardcoded holder or committed slot cache.

On-chain settlement for Range Pools, a concentrated-liquidity Balancer-V3-shaped
DEX on a custom, non-canonical Balancer V3 Vault
(0x955244EDC797A1C1b04134b600f819aC23C76081).

executeRangePool performs the swap Vault-direct via unlock -> swap(EXACT_IN) ->
settle(tokenIn) -> sendTo(tokenOut, recipient), with a Vault-guarded unlock
callback. No Router, no Permit2. Native ETH is wrapped/unwrapped at the edges
since the Vault only handles WETH.

Foundry mainnet-fork parity: realized output == Router.querySwapSingleTokenExactIn
to the wei on both live pools, plus native-ETH in/out and the OnlyVault /
minimum-trade guards.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new KyberSwap executor adapter to support Range Pools (a Balancer-V3-shaped DEX) via the custom Range Vault’s unlock → swap → settle/sendTo transient-accounting flow, plus mainnet-fork parity tests against the Range Router quote function.

Changes:

  • Introduces RangePoolAdapter that executes EXACT_IN swaps via the Range Vault, including native-ETH wrapping/unwrapping support.
  • Vendors minimal interfaces for the Range Vault and WETH used by the adapter.
  • Adds Foundry mainnet-fork parity + guard/symmetry tests for the adapter against live pools.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/adapters/range-pool/RangePoolAdapter.sol New executor adapter implementing Vault-direct swap settlement + native ETH edge handling.
src/adapters/range-pool/IRangeVault.sol Minimal vendored Vault interface + swap types used by adapter/tests.
src/adapters/range-pool/IWETH.sol Minimal WETH interface for deposit/withdraw bridging.
test/adapters/range-pool/RangePoolAdapter.t.sol Mainnet-fork parity tests vs router quote, native in/out cases, and guard/error symmetry checks.
Suppressed comments (2)

src/adapters/range-pool/RangePoolAdapter.sol:101

  • rangePoolUnlockCallback unwraps WETH and performs a native ETH transfer to recipient while still inside the Vault unlock callback. This is an external call to an untrusted address during the Vault’s transient-accounting context and can enable reentrancy into the wider system while the Vault is unlocked. Prefer keeping the callback limited to Vault/token interactions and defer the WETH->ETH unwrap + native transfer until after unlock returns (in executeRangePool).
    if (nativeOut) {
      IRangeVault(VAULT).sendTo(IERC20(WETH), address(this), amountOut);
      IWETH(WETH).withdraw(amountOut);
      recipient.safeTransferNative(amountOut);
    } else {

src/adapters/range-pool/RangePoolAdapter.sol:51

  • executeRangePool doesn’t validate msg.value vs amountIn / tokenIn. If tokenIn is ERC20 but msg.value > 0 (or if native-in and msg.value != amountIn), ETH can be unintentionally trapped in the adapter or the call can behave inconsistently. Also, if native-out unwrapping is deferred out of the Vault callback, executeRangePool should perform the WETH withdrawal + native transfer after unlock returns.
  ) external payable returns (uint256 amountUnused, uint256 amountOut) {
    address pool = data.decodeAddress(0);

    bytes memory result = IRangeVault(VAULT)
      .unlock(

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/adapters/range-pool/RangePoolAdapter.sol
Comment thread test/adapters/range-pool/RangePoolAdapter.t.sol Outdated
_sweep requires at least 2 wei-parity matches; the docstring referenced a nonexistent minHits parameter. Addresses Copilot review comment.
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.

2 participants