Update swapExactTokensForTokens function

This commit is contained in:
cryptoDev222 2021-12-13 16:19:07 -06:00
parent da2eaaba0f
commit 260e0799ee
3 changed files with 148 additions and 55 deletions

View File

@ -1,34 +1,7 @@
pragma solidity ^0.7.0; pragma solidity ^0.7.0;
contract Events { contract Events {
event LogMint( event LogSwapExactTokensForTokens(
uint256 indexed tokenId, uint256 amountOut
uint256 liquidity,
uint256 amtA,
uint256 amtB,
int24 tickLower,
int24 tickUpper
); );
event LogDeposit(
uint256 indexed tokenId,
uint256 liquidity,
uint256 amountA,
uint256 amountB
);
event LogWithdraw(
uint256 indexed tokenId,
uint256 liquidity,
uint256 amountA,
uint256 amountB
);
event LogCollect(
uint256 tokenId,
uint256 amountA,
uint256 amountB
);
event LogBurnPosition(uint256 tokenId);
} }

View File

@ -16,8 +16,17 @@ abstract contract Helpers is DSMath, Basic {
*/ */
INonfungiblePositionManager constant nftManager = INonfungiblePositionManager constant nftManager =
INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
ISwapRouter constant swapRouter = ISwapRouter internal constant swapRouter =
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
bytes32 internal constant POOL_INIT_CODE_HASH =
0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
address constant COMMON_ADDRESSES = [
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, // WETH
0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48, // USDC
0xdAC17F958D2ee523a2206206994597C13D831ec7, // USDT
0x6b175474e89094c44da98b954eedeac495271d0f, // DAI
]
struct MintParams { struct MintParams {
address tokenA; address tokenA;
@ -43,6 +52,85 @@ abstract contract Helpers is DSMath, Basic {
tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1); tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1);
} }
function getPrice(address tokenIn, address tokenOut, uint24 fee)
external
view
returns (uint256 price)
{
IUniswapV3Pool pool = IUniswapV3Pool(factory.getPool(tokenIn, tokenOut, fee);
(uint160 sqrtPriceX96,,,,,,) = pool.slot0();
return uint(sqrtPriceX96).mul(uint(sqrtPriceX96)).mul(1e18) >> (96 * 2);
}
function getPoolAddress(
address tokenA,
address tokenB,
uint24 fee
) internal pure returns (address pool) {
if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
return
computeAddress(
0x1F98431c8aD98523631AE4a59f267346ea31F984,
PoolKey({token0: tokenA, token1: tokenB, fee: fee})
);
}
function computeAddress(address factory, PoolKey memory key)
internal
pure
returns (address pool)
{
require(key.token0 < key.token1);
pool = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(
abi.encode(key.token0, key.token1, key.fee)
),
POOL_INIT_CODE_HASH
)
)
)
)
);
}
function getParams(
address tokenIn,
address tokenOut,
address recipient,
uint24 fee,
uint256 amountIn,
uint256 amountOutMinimum
) internal view returns (ISwapRouter.ExactInputSingleParams memory params) {
params = ISwapRouter.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: fee,
recipient: recipient,
deadline: block.timestamp + 1,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: getPriceLimit(
amountIn,
tokenIn < tokenOut,
tokenIn,
tokenOut,
fee
)
});
}
function swapSingleInput(ISwapRouter.ExactInputSingleParams memory params)
internal
returns (uint256)
{
return (uint256(swapRouter.exactInputSingle(params)));
}
function getMinAmount( function getMinAmount(
TokenInterface token, TokenInterface token,
uint256 amt, uint256 amt,

View File

@ -12,33 +12,65 @@ import {Events} from "./events.sol";
abstract contract UniswapResolver is Helpers, Events { abstract contract UniswapResolver is Helpers, Events {
function swapExactTokensForTokens( function swapExactTokensForTokens(
uint amountIn, address tokenIn,
uint amountOutMin, address tokenOut,
bytes path, address recipient,
address to, uint256 deadline,
uint deadline uint24 fee,
) external virtual override ensure(deadline) returns (uint[] memory amounts) { uint256 amountIn,
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path); uint256 amountOutMinimum
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'); )
TransferHelper.safeTransferFrom( external
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0] payable
); returns (string memory _eventName, bytes memory _eventParam)
_swap(amounts, path, to); {
} address poolAddr = getPoolAddress(tokenIn, tokenOut, fee);
uint256 maxPrice = 0;
uint pathIndex = 0;
function swapTokensForExactTokens( for (uint i = 0; i < COMMON_ADDRESSES.length; i++) {
uint amountOut, uint256 price1 = getPrice(tokenIn, COMMON_ADDRESSES[i], fee);
uint amountInMax, uint256 price2 = getPrice(COMMON_ADDRESSES[i], tokenOut, fee);
bytes path, uint256 price = (price1 + price2) / 2;
address to,
uint deadline if (maxPrice < price) {
) external virtual override ensure(deadline) returns (uint[] memory amounts) { maxPrice = price;
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path); pathIndex = i;
require(amounts[0] <= amountInMax, 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT'); }
TransferHelper.safeTransferFrom( }
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
if (poolAddr != address(0)) {
uint256 price = getPrice(tokenIn, tokenOut, fee);
if (maxPrice < price) {
maxPrice = price;
}
}
IERC20(tokenIn).safeApprove(address(swapRouter), amountIn);
uint256 amountOut1 = swapSingleInput(
getParams(
tokenIn,
COMMON_ADDRESSES[pathIndex],
recipient,
fee,
amountIn,
amountOutMinimum
)
); );
_swap(amounts, path, to); uint256 amountOut = swapSingleInput(
getParams(
COMMON_ADDRESSES[pathIndex],
tokenOut
recipient,
fee,
amountOut1,
amountOutMinimum
)
);
_eventName = "LogSwapExactTokensForTokens(uint256)";
_eventParam = abi.encode(amountOut);
} }
} }