Skip to content

Latest commit

 

History

History
269 lines (193 loc) · 12.2 KB

integrate-woofi-as-liquidity-source.md

File metadata and controls

269 lines (193 loc) · 12.2 KB

Integrate WOOFi as a liquidity source

Contracts

Two main contracts of WOOFi's swap function are as follows:

  • WooPPV2.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.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.sol.

The latest list of supported tokens can be retrieved via the getSupportTokens() function which will return two values:

  • first value: quoteToken address
  • second value: array of baseToken addresses

Contract addresses:

Arbitrum: 0x28D2B949024FE50627f1EbC5f0Ca3Ca721148E40

Optimism: 0x96329d66074EB8386Ae8bFD6698B2E3FDA87e15E

BSC: 0xAA9c15cd603428cA8ddD45e933F8EfE3Afbcc173

Avalanche: 0x020630613E296c3E9b06186f630D1bF97A2B6Ad1

Fantom: 0x6641959FE5EED7166F2254cF04b0d20c96776D9A

Polygon: 0x7Ba560eB735AbDCf9a3a5692272652A0cc81850d

zkSync Era: 0x636DfeB023463F176f87D61E3B604231986bd935

Polygon zkEVM: 0x044c08639bD59BEB4F6ec52c0da6CD47283534E8

Linea: 0x7e1996945eA8866DE873179DC1677E93A4380107

Base: 0xC4E9B633685461E7B7A807D12a246C81f96F31B8

Integrate WOOFi as a liquidity source

When integrating WOOFi as a liquidity source, you can either interact with WooRouterV2.sol or WooPPV2.sol.

Integrating WooPPV2.sol

Another way is to integrate directly with WooPPV2.sol. This approach is slightly more gas efficient, but it requires writing the smart contract code and manually send the fromToken to WooPPV2.sol, which a better choice for apps that already have an aggregation logic.

Contract addresses:

Arbitrum: 0xeFF23B4bE1091b53205E35f3AfCD9C7182bf3062

Optimism: 0xd1778F9DF3eee5473A9640f13682e3846f61fEbC

Avalanche: 0x3b3E4b4741e91aF52d0e9ad8660573E951c88524

Polygon: 0x7081A38158BD050Ae4a86e38E0225Bc281887d7E

BSC: 0xEc054126922a9a1918435c9072c32f1B60cB2B90

Fantom: 0x286ab107c5E9083dBed35A2B5fb0242538F4f9bf

zkSync Era: 0x42ED123EB5266A5B8E2B54B2C76180CCF5e72FEe

Polygon zkEVM: 0xF5d215d9C84778F85746D15762DaF39B9E83a2d6

Linea: 0xF5d215d9C84778F85746D15762DaF39B9E83a2d6

Base - 0xb130a49065178465931d4f887056328CeA5D723f

Interface

    /// @notice The quote token address (immutable).
    /// @return address of quote token
    function quoteToken() external view returns (address);

    /// @notice Gets the pool size of the specified token (swap liquidity).
    /// @param token the token address
    /// @return the pool size
    function poolSize(address token) external view returns (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`
    function tryQuery(
        address fromToken,
        address toToken,
        uint256 fromAmount
    ) external view returns (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`
    function query(
        address fromToken,
        address toToken,
        uint256 fromAmount
    ) external view returns (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 receive
    function swap(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        uint256 minToAmount,
        address to,
        address rebateTo
    ) external returns (uint256 realToAmount);

Sample code

    IWooPPV2 public wooPool; // IWooPPV2 smart contrac
    
    function sampleFunc(...) external {
        ... your business code ..

        // query the trade
        address fromToken = WBTC_ADDR;
        address toToken = USDT_ADDR;
        uint256 amountIn = 10000000; // 0.1 btc
        
        uint256 amountOut = wooPool.query(fromToken, toToken, amountIn);
        // or wooPool.tryQuery if you don't need the swap.
 
        // swap
        IERC20(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` ...
    }
    

sPMM offchain simulation

For aggregators running offchain routing simulation, you can find the typescript implementation of WOOFi's sPMM algorithm in the github (to be added soon).

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.

Router Contract Addresses

Arbitrum: 0x9aEd3A8896A85FE9a8CAc52C9B402D092B629a30

Optimism: 0xEAf1Ac8E89EA0aE13E0f03634A4FF23502527024

Avalanche: 0xC22FBb3133dF781E6C25ea6acebe2D2Bb8CeA2f9

Polygon: 0x817Eb46D60762442Da3D931Ff51a30334CA39B74

BSC: 0xC90bFE9951a4Efbf20aCa5ECd9966b2bF8A01294

Fantom: 0x382A9b0bC5D29e96c3a0b81cE9c64d6C8F150Efb

zkSync Era: 0xfd505702b37Ae9b626952Eb2DD736d9045876417

Polygon zkEVM: 0x39d361E66798155813b907A70D6c2e3FdaFB0877

Linea: 0x39d361E66798155813b907A70D6c2e3FdaFB0877

Base: 0x27425e9FB6A9A625E8484CFD9620851D1Fa322E5

Interface

    /// @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 receive
    function querySwap(
        address fromToken,
        address toToken,
        uint256 fromAmount
    ) external view returns (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 receive
    function tryQuerySwap(
        address fromToken,
        address toToken,
        uint256 fromAmount
    ) external view returns (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 receive
    function swap(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        uint256 minToAmount,
        address payable to,
        address rebateTo
    ) external payable returns (uint256 realToAmount);

Sample code

// Query Part
address fromToken = 0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f;  // wbtc
address toToken = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;    // usdc
uint256 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 Part
uint256 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 8
  19000000000,    // min amount = 19000 usdc (price: 19500)
  address(this),  // the address to receive the swap fund
  address(0)      // the rebateTo address
);