Skip to content

Commit

Permalink
Merge pull request #292 from consenlabs/v6-update-and-fix-ua-router-a…
Browse files Browse the repository at this point in the history
…ddress

support SwapRouter02 and update UniversalRouter addr
  • Loading branch information
charlesjhongc authored Sep 12, 2023
2 parents 6f9a9d4 + b4fdf37 commit 4b55012
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 5 deletions.
8 changes: 6 additions & 2 deletions contracts/UniAgent.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ contract UniAgent is IUniAgent, Ownable, TokenCollector {

address private constant v2Router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address private constant v3Router = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
address payable private constant universalRouter = payable(0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B);
address private constant swapRouter02 = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45;
address payable private constant universalRouter = payable(0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD);

constructor(address _owner, address _uniswapPermit2, address _allowanceTarget) Ownable(_owner) TokenCollector(_uniswapPermit2, _allowanceTarget) {}

Expand All @@ -34,6 +35,7 @@ contract UniAgent is IUniAgent, Ownable, TokenCollector {
// ignore return value and proceed anyway since three calls are independent
tokens[i].call(abi.encodeCall(IERC20.approve, (v2Router, type(uint256).max)));
tokens[i].call(abi.encodeCall(IERC20.approve, (v3Router, type(uint256).max)));
tokens[i].call(abi.encodeCall(IERC20.approve, (swapRouter02, type(uint256).max)));
}
}

Expand Down Expand Up @@ -82,7 +84,7 @@ contract UniAgent is IUniAgent, Ownable, TokenCollector {
// deposit directly into router if it's universal router
_collect(inputToken, msg.sender, universalRouter, inputAmount, userPermit);
} else {
// v2 v3 use transferFrom
// v2, v3, swapRouter02 use transferFrom
_collect(inputToken, msg.sender, address(this), inputAmount, userPermit);
}
}
Expand All @@ -101,6 +103,8 @@ contract UniAgent is IUniAgent, Ownable, TokenCollector {
return v2Router;
} else if (routerType == RouterType.V3Router) {
return v3Router;
} else if (routerType == RouterType.SwapRouter02) {
return swapRouter02;
} else if (routerType == RouterType.UniversalRouter) {
return universalRouter;
}
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IUniAgent.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface IUniAgent {
enum RouterType {
V2Router,
V3Router,
SwapRouter02,
UniversalRouter
}

Expand Down
50 changes: 50 additions & 0 deletions contracts/interfaces/IUniswapSwapRouter02.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface ISwapRouter02 {
function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to) external payable returns (uint256 amountOut);

function swapTokensForExactTokens(uint256 amountOut, uint256 amountInMax, address[] calldata path, address to) external payable returns (uint256 amountIn);

struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}

function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);

struct ExactInputParams {
bytes path;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
}

function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);

struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}

function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);

struct ExactOutputParams {
bytes path;
address recipient;
uint256 amountOut;
uint256 amountInMaximum;
}

function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint": "solhint \"contracts/**/*.sol\"",
"compile": "forge build --force",
"test-foundry-local": "DEPLOYED=false forge test --no-match-path 'test/forkMainnet/*.t.sol'",
"test-foundry-fork": "DEPLOYED=false forge test --fork-url $MAINNET_NODE_RPC_URL --fork-block-number 16075500 --match-path 'test/forkMainnet/*.t.sol'",
"test-foundry-fork": "DEPLOYED=false forge test --fork-url $MAINNET_NODE_RPC_URL --fork-block-number 17900000 --match-path 'test/forkMainnet/*.t.sol'",
"gas-report-local": "yarn test-foundry-local --gas-report",
"gas-report-fork": "yarn test-foundry-fork --gas-report"
},
Expand Down
73 changes: 73 additions & 0 deletions test/forkMainnet/UniAgent/SwapRouter02.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { ISwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";
import { IUniswapRouterV2 } from "contracts/interfaces/IUniswapRouterV2.sol";
import { IUniswapV3Quoter } from "contracts/interfaces/IUniswapV3Quoter.sol";
import { IUniAgent } from "contracts/interfaces/IUniAgent.sol";
import { UniswapV3 } from "contracts/libraries/UniswapV3.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniAgentTest } from "test/forkMainnet/UniAgent/Setup.t.sol";

contract SwapRouter02Test is UniAgentTest {
using BalanceSnapshot for Snapshot;

IUniswapRouterV2 v2Router = IUniswapRouterV2(UNISWAP_V2_ADDRESS);
IUniswapV3Quoter v3Quoter = IUniswapV3Quoter(UNISWAP_V3_QUOTER_ADDRESS);
uint256 defaultOutputAmount;
uint24 defaultFee = 3000;
uint24[] v3Fees = [defaultFee];

function setUp() public override {
super.setUp();
}

function testV2SwapExactTokensForTokens() public {
// USDT -> CRV
Snapshot memory userInputToken = BalanceSnapshot.take({ owner: user, token: defaultInputToken });
Snapshot memory recvOutputToken = BalanceSnapshot.take({ owner: recipient, token: defaultOutputToken });

uint256[] memory amounts = v2Router.getAmountsOut(defaultInputAmount, defaultPath);
uint256 outputAmount = amounts[amounts.length - 1];
uint256 minOutputAmount = (defaultOutputAmount * 95) / 100; // default 5% slippage tolerance
bytes memory payload = abi.encodeCall(ISwapRouter02.swapExactTokensForTokens, (defaultInputAmount, minOutputAmount, defaultPath, recipient));

vm.prank(user);
uniAgent.swap(IUniAgent.RouterType.SwapRouter02, defaultInputToken, defaultInputAmount, payload, defaultUserPermit);

userInputToken.assertChange(-int256(defaultInputAmount));
// recipient should receive exact amount of quote from Uniswap
recvOutputToken.assertChange(int256(outputAmount));
}

function testV3ExactInputSingle() public {
// USDT -> CRV
Snapshot memory userInputToken = BalanceSnapshot.take({ owner: user, token: defaultInputToken });
Snapshot memory recvOutputToken = BalanceSnapshot.take({ owner: recipient, token: defaultOutputToken });

bytes memory encodedPath = UniswapV3.encodePath(defaultPath, v3Fees);
defaultOutputAmount = v3Quoter.quoteExactInput(encodedPath, defaultInputAmount);
uint256 minOutputAmount = (defaultOutputAmount * 95) / 100; // default 5% slippage tolerance
bytes memory payload = abi.encodeCall(
ISwapRouter02.exactInputSingle,
(
ISwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: recipient,
amountIn: defaultInputAmount,
amountOutMinimum: minOutputAmount,
sqrtPriceLimitX96: 0
})
)
);

vm.prank(user);
uniAgent.swap(IUniAgent.RouterType.SwapRouter02, defaultInputToken, defaultInputAmount, payload, defaultUserPermit);

userInputToken.assertChange(-int256(defaultInputAmount));
// recipient should receive exact amount of quote from Uniswap
recvOutputToken.assertChange(int256(defaultOutputAmount));
}
}
1 change: 1 addition & 0 deletions test/utils/config/arbitrumMainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"UNISWAP_V3_ADDRESS": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"UNISWAP_V3_QUOTER_ADDRESS": "0x0000000000000000000000000000000000000000",
"UNISWAP_PERMIT2_ADDRESS": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"UNISWAP_SWAP_ROUTER_02_ADDRESS": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0x4648a43B2C14Da09FdF82B161150d3F634f40491",
"CURVE_USDT_POOL_ADDRESS": "0x0000000000000000000000000000000000000000",
"CURVE_COMPOUND_POOL_ADDRESS": "0x0000000000000000000000000000000000000000",
Expand Down
3 changes: 2 additions & 1 deletion test/utils/config/goerli.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"UNISWAP_V3_ADDRESS": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"UNISWAP_V3_QUOTER_ADDRESS": "0x0000000000000000000000000000000000000000",
"UNISWAP_PERMIT2_ADDRESS": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0x4648a43B2C14Da09FdF82B161150d3F634f40491",
"UNISWAP_SWAP_ROUTER_02_ADDRESS": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",
"CURVE_USDT_POOL_ADDRESS": "0x0000000000000000000000000000000000000000",
"CURVE_COMPOUND_POOL_ADDRESS": "0x0000000000000000000000000000000000000000",
"CURVE_Y_POOL_ADDRESS": "0x0000000000000000000000000000000000000000",
Expand Down
1 change: 1 addition & 0 deletions test/utils/config/local.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"UNISWAP_V3_ADDRESS": "0x000000000000000000000000000000000000000",
"UNISWAP_V3_QUOTER_ADDRESS": "0x000000000000000000000000000000000000000",
"UNISWAP_PERMIT2_ADDRESS": "0x000000000000000000000000000000000000000",
"UNISWAP_SWAP_ROUTER_02_ADDRESS": "0x000000000000000000000000000000000000000",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0x000000000000000000000000000000000000000",
"CURVE_USDT_POOL_ADDRESS": "0x000000000000000000000000000000000000000",
"CURVE_COMPOUND_POOL_ADDRESS": "0x000000000000000000000000000000000000000",
Expand Down
3 changes: 2 additions & 1 deletion test/utils/config/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"UNISWAP_V3_ADDRESS": "0xE592427A0AEce92De3Edee1F18E0157C05861564",
"UNISWAP_V3_QUOTER_ADDRESS": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
"UNISWAP_PERMIT2_ADDRESS": "0x000000000022d473030f116ddee9f6b43ac78ba3",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",
"UNISWAP_SWAP_ROUTER_02_ADDRESS": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
"UNISWAP_UNIVERSAL_ROUTER_ADDRESS": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",
"CURVE_USDT_POOL_ADDRESS": "0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C",
"CURVE_COMPOUND_POOL_ADDRESS": "0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56",
"CURVE_Y_POOL_ADDRESS": "0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51",
Expand Down

0 comments on commit 4b55012

Please sign in to comment.