4

I have created a swap contract for superfluid(https://superfluid.finance) super tokens, which swaps anySuperToken <-> anySuperToken, Essentially its just an ERC20 token with additional capabilities.

My swap contract works the following way -

  1. To swap SuperTokenA -> SuperTokenB.
  2. It unwraps the SuperTokenA -> TokenA, using the function downgrade.
  3. Swaps for the desired token using uniswapV3.
  4. Upgrades to superToken of superfluid and send the tokens back to the user.

This is my complete contract for the super token swap, the contract is also deployed on -

Rinkeby - https://rinkeby.etherscan.io/address/0xa48fe52fe42e7107c717d82dfa61cf5ff6919347 Polygon - https://polygonscan.com/address/0x0983c50085C81A7F41598Eb46a29001989102119

The same contract is deployed in both the places, I also tested the contract on Rinkeby - https://rinkeby.etherscan.io/tx/0xa896eadf0825365e2a7d9bd6c660c6f1d594935e79859657da040b7aeeefdebb where the swap is successful.

But I am getting STF error on polygon - which generally means that I have not given approval to spend the token, but I have given the approval.

These are the parameters I am using if someone wants to try it out -

_from = 0xCAa7349CEA390F89641fe306D93591f87595dc1F
_to = 0x27e1e4E6BC79D93032abef01025811B7E4727e85
amountIn = 10000000000000
amountOutMin = 0
path = [0x2791bca1f2de4661ed88a30c99a7a9449aa84174, 0x7ceb23fd6bc0add59e62ac25578270cff1b9f619]
poolFees = [500] // There is a uniswap USDC/WETH pool with 0.05% fees

The complete contract can also be found here - https://github.com/Ricochet-Exchange/ricochet-super-swap/blob/main/contracts/RexSuperSwap.sol

//SPDX-License-Identifier: MIT
 pragma solidity ^0.7.6;
 pragma abicoder v2;

 import {ISuperToken} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
 import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
 import "@uniswap/swap-router-contracts/contracts/interfaces/ISwapRouter02.sol";

 contract RexSuperSwap {
     ISwapRouter02 public immutable swapRouter;

     event SuperSwapComplete(uint256 amountOut);

     constructor(ISwapRouter02 _swapRouter) {
         swapRouter = _swapRouter;
     }

     /**
      * @dev Swaps `amountIn` of `_from` SuperToken for at least `amountOutMin`
      * of `_to` SuperToken through `path` with `poolFees` fees for each pair.
      *
      * Returns the amount of `_to` SuperToken received.
      */
     function swap(
         ISuperToken _from,
         ISuperToken _to,
         uint256 amountIn,
         uint256 amountOutMin,
         address[] memory path,
         uint24[] memory poolFees // Example: 0.3% * 10000 = 3000
     ) external returns (uint256 amountOut) {
         require(amountIn > 0, "Amount cannot be 0");
         require(path.length > 1, "Incorrect path");
         require(
             poolFees.length == path.length - 1,
             "Incorrect poolFees length"
         );

         // Step 1: Get underlying tokens and verify path
         address fromBase = _from.getUnderlyingToken();
         address toBase = _to.getUnderlyingToken();

         require(path[0] == fromBase, "Invalid 'from' base token");
         require(path[path.length - 1] == toBase, "Invalid 'to' base token");

         // Step 2: Transfer SuperTokens from sender
         TransferHelper.safeTransferFrom(
             address(_from),
             msg.sender,
             address(this),
             amountIn
         );

         // Step 3: Downgrade
         _from.downgrade(amountIn);

         // Step 4: Approve and Swap

         // Encode the path for swap
         bytes memory encodedPath;
         for (uint256 i = 0; i < path.length; i++) {
             if (i == path.length - 1) {
                 encodedPath = abi.encodePacked(encodedPath, path[i]);
             } else {
                 encodedPath = abi.encodePacked(
                     encodedPath,
                     path[i],
                     poolFees[i]
                 );
             }
         }

         // Approve the router to spend token supplied (fromBase).
         TransferHelper.safeApprove(
             fromBase,
             address(swapRouter),
             amountIn
         );

         IV3SwapRouter.ExactInputParams memory params = IV3SwapRouter
             .ExactInputParams({
                 path: encodedPath,
                 recipient: address(this),
                 amountIn: amountIn,
                 amountOutMinimum: amountOutMin
             });

         // Execute the swap
         amountOut = swapRouter.exactInput(params);

         // Step 5: Upgrade and send tokens back
         TransferHelper.safeApprove(address(toBase), address(_to), amountOut);
         _to.upgrade(amountOut);
         TransferHelper.safeApprove(address(_to), msg.sender, amountOut);
         TransferHelper.safeTransferFrom(
             address(_to),
             address(this),
             msg.sender,
             amountOut
         );

         emit SuperSwapComplete(amountOut);
     }
 }

0 Answers0