Skip to content

feat: add Wasabi Prop AMM adapter and related interfaces#1

Closed
WEBthe3rd wants to merge 5 commits intoKyberNetwork:mainfrom
dev-wasabi:feat/wasabi-prop-amm-adapter
Closed

feat: add Wasabi Prop AMM adapter and related interfaces#1
WEBthe3rd wants to merge 5 commits intoKyberNetwork:mainfrom
dev-wasabi:feat/wasabi-prop-amm-adapter

Conversation

@WEBthe3rd
Copy link
Copy Markdown

@WEBthe3rd WEBthe3rd commented Feb 13, 2026

Summary

  • Add a KyberSwap DEX adapter for the Wasabi Prop AMM, enabling the KyberSwap aggregator to route swaps through Wasabi's oracle-anchored AMM pools on Base
  • The adapter interacts directly with PropPool contracts (not through the PropSwapRouter), following the guideline to prefer direct pool interaction

Details

Each Wasabi Prop AMM pool pairs a single base token (e.g. WETH) with USDC as the quote token. The adapter handles one pool per call -- for token-to-token routes (e.g. WETH -> WBTC), the aggregator chains two calls through USDC.

The data parameter encodes only the pool address:

bytes memory data = abi.encode(poolAddress);

ERC20 output tokens are left in the adapter for the framework to collect. Native token wrapping/unwrapping is handled by KyberSwap's internal flow and does not need to be implemented in the adapter.

Deployment note: The adapter contract must be granted AUTHORIZED_SWAPPER_ROLE (role 100) on the PropPoolFactory's access manager after deployment.

New files

File Description
src/adapters/wasabi-prop-amm/WasabiPropAmmAdapter.sol Adapter contract
src/adapters/wasabi-prop-amm/IPropPool.sol Minimal PropPool interface
test/adapters/wasabi-prop-amm/WasabiPropAmmAdapter.t.sol Fuzz test using a Base mainnet fork

Test plan

  • Fuzz test: ERC20 swaps in both directions (WETH -> USDC, USDC -> WETH)
  • Test passes across 32 fuzz runs against a live Base mainnet fork

Copilot AI review requested due to automatic review settings February 13, 2026 17:40
Copy link
Copy Markdown

Copilot AI left a comment

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 DEX adapter to let the aggregator route swaps through Wasabi Prop AMM pools (Base), including native ETH wrapping/unwrapping support.

Changes:

  • Introduces WasabiPropAmmAdapter with support for native ETH in/out via WETH.
  • Adds minimal IPropPool and IWETH interfaces for pool interaction and wrapping.
  • Adds fork-based fuzz tests for ERC20 and native ETH swap paths.

Reviewed changes

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

File Description
src/adapters/wasabi-prop-amm/WasabiPropAmmAdapter.sol Implements PropPool swap execution and native ETH wrap/unwrap handling
src/adapters/wasabi-prop-amm/IPropPool.sol Minimal PropPool interface for swapping and token discovery
src/adapters/wasabi-prop-amm/IWETH.sol Minimal WETH interface used for deposit/withdraw
test/adapters/wasabi-prop-amm/WasabiPropAmmAdapter.t.sol Base fork fuzz tests for ERC20 swaps + native ETH in/out scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +55
address pool = data.decodeAddress(0);

// Resolve actual ERC20 token address for input (native ETH -> WETH)
address actualTokenIn = tokenIn.isNative() ? WETH : tokenIn;

// Wrap native ETH to WETH if needed
if (tokenIn.isNative()) {
if (msg.value != amountIn) revert InvalidMsgValue();
IWETH(WETH).deposit{value: amountIn}();
} else if (msg.value != 0) {
revert InvalidMsgValue();
}

// Approve pool to pull tokenIn from this adapter
actualTokenIn.forceApprove(pool, amountIn);

// Execute swap -- pool pulls tokenIn, sends tokenOut back to this contract
amountOut = IPropPool(pool).swapExactInput(actualTokenIn, amountIn, 1);

// Only explicitly transfer if native ETH is requested as output;
// ERC20 outputs are left in the adapter for the framework to collect
if (tokenOut.isNative()) {
IWETH(WETH).withdraw(amountOut);
TokenHelper.safeTransferNative(recipient, amountOut);
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

executeWasabiPropAmm doesn’t validate that tokenIn/tokenOut match the pool’s pair. If the caller supplies mismatched tokens, the swap may still succeed (outputting the pool’s “other” token) while the framework believes it received tokenOut; additionally, tokenOut.isNative() will attempt to unwrap WETH even if the pool didn’t output WETH. Consider checking IPropPool(pool).getBaseToken()/getQuoteToken() and reverting when (actualTokenIn, actualTokenOut) isn’t exactly the pool’s pair (with native mapped to WETH).

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +54
// Only explicitly transfer if native ETH is requested as output;
// ERC20 outputs are left in the adapter for the framework to collect
if (tokenOut.isNative()) {
IWETH(WETH).withdraw(amountOut);
TokenHelper.safeTransferNative(recipient, amountOut);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

ERC20 outputs are left in the adapter, so the recipient parameter is ignored for non-native tokenOut. This differs from the other adapters in this repo (which send output directly to recipient) and also leaves token balances sitting in an externally-callable contract; any leftover balance can be pulled out by a subsequent call that approves a malicious pool and uses that balance as amountIn. Consider transferring ERC20 tokenOut to recipient (or adding access control / an explicit, safe collection mechanism if retention is required).

Suggested change
// Only explicitly transfer if native ETH is requested as output;
// ERC20 outputs are left in the adapter for the framework to collect
if (tokenOut.isNative()) {
IWETH(WETH).withdraw(amountOut);
TokenHelper.safeTransferNative(recipient, amountOut);
// Transfer output to the recipient. If native ETH is requested, unwrap WETH first;
// otherwise, transfer the ERC20 tokenOut directly.
if (tokenOut.isNative()) {
IWETH(WETH).withdraw(amountOut);
TokenHelper.safeTransferNative(recipient, amountOut);
} else {
tokenOut.safeTransfer(recipient, amountOut);

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +49
// Execute swap -- pool pulls tokenIn, sends tokenOut back to this contract
amountOut = IPropPool(pool).swapExactInput(actualTokenIn, amountIn, 1);

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

swapExactInput is called with minAmountOut hardcoded to 1, effectively disabling slippage protection at the adapter layer even though the PropPool API supports it. If the surrounding framework can provide a minimum acceptable output, consider encoding/decoding it from data (or adding a parameter) and passing it through.

Copilot uses AI. Check for mistakes.
Comment thread test/adapters/wasabi-prop-amm/WasabiPropAmmAdapter.t.sol
@thepluck
Copy link
Copy Markdown
Member

Hi @WEBthe3rd, if the pool contracts do not support the native token directly, you can ignore it since we have an internal flow to wrap it if needed 😄

@WEBthe3rd
Copy link
Copy Markdown
Author

Hi @WEBthe3rd, if the pool contracts do not support the native token directly, you can ignore it since we have an internal flow to wrap it if needed 😄

Got it, I just stripped out the native token handling. Let me know if any other changes are needed!

@thepluck
Copy link
Copy Markdown
Member

thepluck commented Mar 2, 2026

@WEBthe3rd pls allow maintainers to commit to your branch

@thepluck thepluck closed this Mar 5, 2026
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.

4 participants