Two main contracts of WOOFi's swap function are as follows:
WooPPV2_1.sol: the main swap contract that handles the logic operation, including setting the token info, calculating slippage, calculating the exchange amount and executing trades. it stores all tokens that are supported for trading. In this contract, it defines quote token and base token. Quote token is the reference token (i.e. stablecoins) in the contract and there is only one quote token. The contract can have multiple base tokens and they can be added by the strategist.
WooRouterV2.sol: the router contract that frontend users interact with. It interacts with the lower layer WooPPV2.sol to execute the sell logic and send back users the desired amount of tokens. This contract also implements the logic to route user orders to 3rd party aggregator (e.g. 1inch) when WooPPV2.sol does not have sufficient liquidity.
Supported assets
Adding IntegrationHelper.sol
WooPPV2_1.sol has one quote token which is typically the dominant stablecoin of each chain and multiple base tokens. A IntegrationHelper.sol contract is deployed on each supported chain which contains the address of the quote token and the list of tradable base token addresses in WooPPV2_1.sol.
The latest list of supported tokens can be retrieved via the getSupportTokens() function which will return two values:
When integrating WOOFi as a liquidity source, you can either interact with WooRouterV2.sol or WooPPV2_1.sol.
Integrating WooPPV2_1.sol
Another way is to integrate directly with WooPPV2_1.sol. This approach is slightly more gas efficient, but it requires writing the smart contract code and manually send the fromToken to WooPPV2_1.sol, which a better choice for apps that already have an aggregation logic.
Contract addresses:
Same address across Arbitrum, Avalanche, BSC, Optimism, Polygon PoS, Linea, Base, Mantle: 0xEd9e3f98bBed560e66B89AaC922E29D4596A9642
/// @notice The quote token address (immutable)./// @return address of quote tokenfunctionquoteToken() externalviewreturns (address);/// @notice Gets the pool size of the specified token (swap liquidity)./// @param token the token address/// @return the pool sizefunctionpoolSize(address token) externalviewreturns (uint256);/// @notice Query the amount to swap `fromToken` to `toToken`, without checking the pool reserve balance./// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of `fromToken` to swap/// @return toAmount the swapped amount of `toToken`functiontryQuery(address fromToken,address toToken,uint256 fromAmount ) externalviewreturns (uint256 toAmount);/// @notice Query the amount to swap `fromToken` to `toToken`, with checking the pool reserve balance./// @dev tx reverts when 'toToken' balance is insufficient./// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of `fromToken` to swap/// @return toAmount the swapped amount of `toToken`functionquery(address fromToken,address toToken,uint256 fromAmount ) externalviewreturns (uint256 toAmount);/// @notice Swap `fromToken` to `toToken`./// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of `fromToken` to swap/// @param minToAmount the minimum amount of `toToken` to receive/// @param to the destination address/// @param rebateTo the rebate address (optional, can be address ZERO)/// @return realToAmount the amount of toToken to receivefunctionswap(address fromToken,address toToken,uint256 fromAmount,uint256 minToAmount,address to,address rebateTo ) externalreturns (uint256 realToAmount);
Sample code
IWooPPV2 public wooPool; // IWooPPV2 smart contracfunctionsampleFunc(...) external { ... your business code ..// query the tradeaddress fromToken = WBTC_ADDR;address toToken = USDT_ADDR;uint256 amountIn =10000000; // 0.1 btcuint256 amountOut = wooPool.query(fromToken, toToken, amountIn);// or wooPool.tryQuery if you don't need the swap.// swapIERC20(toToken).safeTransfer(address(wooPool), amountIn);uint256 realToAmount = wooPool.swap( fromToken, toToken, amountIn, amountOut *99/100,address(this),address(0) ); ... other business code to deal with `toToken` ... }
Price check with Wooracle
WOOFi's oracle has a few price check implemented, find the addresses of the wooracle contract in On-chain price feeds.
checking against the 3rd party oracle price e.g. ChainLink and Pyth
set the price range a swap can be executed against the current price
Integrating WooRouterV2.sol
The straightforward way is interacting with WooRouterV2.sol contract which provides the query and swap for any two specified tokens. It streamlined the logic of swapping native blockchain coin and swapping between any of the two supported assets, which simplifies the integration for apps that do not have an existing aggregation logic.
Contract addresses:
Same address across Arbitrum, Avalanche, BSC, Optimism, Polygon PoS, Linea, Base, Mantle: 0x4c4AF8DBc524681930a27b2F1Af5bcC8062E6fB7
/// @dev query the amount to swap fromToken -> toToken/// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of fromToken to swap/// @return toAmount the predicted amount to receivefunctionquerySwap(address fromToken,address toToken,uint256 fromAmount ) externalviewreturns (uint256 toAmount);/// @dev query the amount to swap fromToken -> toToken,/// WITHOUT checking the reserve balance; so it/// always returns the quoted amount (for reference)./// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of fromToken to swap/// @return toAmount the predicted amount to receivefunctiontryQuerySwap(address fromToken,address toToken,uint256 fromAmount ) externalviewreturns (uint256 toAmount);/// @notice Swap `fromToken` to `toToken`./// @param fromToken the from token/// @param toToken the to token/// @param fromAmount the amount of `fromToken` to swap/// @param minToAmount the minimum amount of `toToken` to receive/// @param to the destination address/// @param rebateTo the rebate address (optional, can be 0)/// @return realToAmount the amount of toToken to receivefunctionswap(address fromToken,address toToken,uint256 fromAmount,uint256 minToAmount,address payable to,address rebateTo ) externalpayablereturns (uint256 realToAmount);
Sample code
// Query Partaddress fromToken =0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f; // wbtcaddress toToken =0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8; // usdcuint256 amount1 = wooRouter.querySwap( fromToken, toToken,100000000// 1 wbtc amount in decimal 8)uint256 amount2 = wooRouter.tryQuerySwap( fromToken, toToken,100000000); // 1 wbtc amount in decimal 8// NOTE: when the balance reserve is enough for swap, amount1 = amount2;// otherwise, amount2 is still calculated based on wooracle price and woo market-making// formula, but the amount1 qeury simply failed with insufficient balance error.// Swap Partuint256 amountIn =100000000;IERC20(fromToken).safeApprove(address(wooRouter), amountIn);uint256 realToAmount = wooRouter.swap( fromToken,// wbtc token address toToken,// usdc token address amountIn,// wbtc amount to swap in decimal 819000000000,// min amount = 19000 usdc (price: 19500)address(this),// the address to receive the swap fundaddress(0) // the rebateTo address);