文件 1 的 15:IERC20.sol
pragma solidity =0.7.6;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
文件 2 的 15:IImpossibleERC20.sol
pragma solidity =0.7.6;
interface IImpossibleERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
文件 3 的 15:IImpossiblePair.sol
pragma solidity =0.7.6;
import './IImpossibleERC20.sol';
interface IImpossiblePair is IImpossibleERC20 {
enum TradeState {
SELL_ALL,
SELL_TOKEN_0,
SELL_TOKEN_1,
SELL_NONE
}
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint256 reserve0, uint256 reserve1);
event ChangeInvariant(bool _isXybk, uint256 _newBoost0, uint256 _newBoost1);
event UpdatedTradeFees(uint256 _oldFee, uint256 _newFee);
event UpdatedDelay(uint256 _oldDelay, uint256 _newDelay);
event UpdatedTradeState(TradeState _tradeState);
event UpdatedWithdrawalFeeRatio(uint256 _oldWithdrawalFee, uint256 _newWithdrawalFee);
event UpdatedBoost(
uint32 _oldBoost0,
uint32 _oldBoost1,
uint32 _newBoost0,
uint32 _newBoost1,
uint256 _start,
uint256 _end
);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint256, uint256);
function calcBoost() external view returns (uint256, uint256);
function mint(address) external returns (uint256);
function burn(address) external returns (uint256, uint256);
function swap(
uint256,
uint256,
address,
bytes calldata
) external;
function skim(address to) external;
function sync() external;
function getPairSettings()
external
view
returns (
uint16,
TradeState,
bool
);
function delay() external view returns (uint256);
function initialize(
address,
address,
address,
address
) external;
}
文件 4 的 15:IImpossibleRouter.sol
pragma solidity >=0.6.2;
interface IImpossibleRouter {
function factory() external view returns (address factoryAddr);
function routerExtension() external view returns (address routerExtensionAddr);
function wrapFactory() external view returns (address wrapFactoryAddr);
function WETH() external view returns (address WETHAddr);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
}
文件 5 的 15:IImpossibleRouterExtension.sol
pragma solidity =0.7.6;
import './IImpossiblePair.sol';
interface IImpossibleRouterExtension {
function factory() external returns (address factoryAddr);
function swap(uint256[] memory amounts, address[] memory path) external;
function swapSupportingFeeOnTransferTokens(address[] memory path) external;
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidity(
address tokenA,
address tokenB,
address pair,
uint256 amountAMin,
uint256 amountBMin
) external returns (uint256 amountA, uint256 amountB);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut
) external view returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
address tokenIn,
address tokenOut
) external view returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);
}
文件 6 的 15:IImpossibleSwapFactory.sol
pragma solidity =0.7.6;
interface IImpossibleSwapFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
event UpdatedGovernance(address governance);
function feeTo() external view returns (address);
function governance() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setGovernance(address) external;
}
文件 7 的 15:IImpossibleWrappedToken.sol
pragma solidity =0.7.6;
import './IERC20.sol';
interface IImpossibleWrappedToken is IERC20 {
function deposit(address, uint256) external returns (uint256);
function withdraw(address, uint256) external returns (uint256);
function amtToUnderlyingAmt(uint256) external returns (uint256);
}
文件 8 的 15:IImpossibleWrapperFactory.sol
pragma solidity =0.7.6;
interface IImpossibleWrapperFactory {
event WrapCreated(address, address, uint256, uint256);
event WrapDeleted(address, address);
function tokensToWrappedTokens(address) external view returns (address);
function wrappedTokensToTokens(address) external view returns (address);
}
文件 9 的 15:IWETH.sol
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}
文件 10 的 15:ImpossibleLibrary.sol
pragma solidity >=0.5.0;
import '../interfaces/IImpossiblePair.sol';
import '../interfaces/IERC20.sol';
import './SafeMath.sol';
import './Math.sol';
library ImpossibleLibrary {
using SafeMath for uint256;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'ImpossibleLibrary: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'ImpossibleLibrary: ZERO_ADDRESS');
}
function pairFor(
address factory,
address tokenA,
address tokenB
) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'20bf34d7ad42a982d8700c48fa133ba50b84584b001fdda29b39238e494ff348'
)
)
)
);
}
function getReserves(
address factory,
address tokenA,
address tokenB
)
internal
view
returns (
uint256 reserveA,
uint256 reserveB,
address pair
)
{
(address token0, ) = sortTokens(tokenA, tokenB);
pair = pairFor(factory, tokenA, tokenB);
(uint256 reserve0, uint256 reserve1) = IImpossiblePair(pair).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) internal pure returns (uint256 amountB) {
require(amountA > 0, 'ImpossibleLibrary: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'ImpossibleLibrary: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
function xybkComputeK(
uint256 boost0,
uint256 boost1,
uint256 balance0,
uint256 balance1
) internal pure returns (uint256 k) {
uint256 boost = (balance0 > balance1) ? boost0.sub(1) : boost1.sub(1);
uint256 denom = boost.mul(2).add(1);
uint256 term = boost.mul(balance0.add(balance1)).div(denom.mul(2));
k = (Math.sqrt(term**2 + balance0.mul(balance1).div(denom)) + term)**2;
}
function calcArtiLiquidityTerm(uint256 _boost, uint256 _sqrtK) internal pure returns (uint256) {
return (_boost - 1).mul(_sqrtK);
}
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256 amountOut) {
require(amountIn > 0, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
uint256 reserveIn;
uint256 reserveOut;
uint256 amountInPostFee;
address pair;
bool isMatch;
{
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut);
}
uint256 artiLiqTerm;
bool isXybk;
{
uint256 fee;
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
amountInPostFee = amountIn.mul(10000 - fee);
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
}
if (isXybk) {
(uint256 boost0, uint256 boost1) = IImpossiblePair(pair).calcBoost();
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
if (amountInPostFee.add(reserveIn.mul(10000)) >= sqrtK.mul(10000)) {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
if (reserveIn < sqrtK && boost0 != boost1) {
amountOut = reserveOut.sub(sqrtK);
amountInPostFee = amountInPostFee.sub((sqrtK.sub(reserveIn)).mul(10000));
reserveIn = sqrtK;
reserveOut = sqrtK;
}
} else {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
}
}
uint256 numerator = amountInPostFee.mul(reserveOut.add(artiLiqTerm));
uint256 denominator = (reserveIn.add(artiLiqTerm)).mul(10000).add(amountInPostFee);
uint256 lastSwapAmountOut = numerator / denominator;
amountOut = (lastSwapAmountOut > reserveOut) ? reserveOut.add(amountOut) : lastSwapAmountOut.add(amountOut);
}
function getAmountIn(
uint256 amountOut,
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256 amountIn) {
require(amountOut > 0, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
uint256 reserveIn;
uint256 reserveOut;
uint256 artiLiqTerm;
uint256 fee;
bool isMatch;
{
bool isXybk;
uint256 boost0;
uint256 boost1;
{
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
}
{
address pair;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut);
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
(boost0, boost1) = IImpossiblePair(pair).calcBoost();
}
if (isXybk) {
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
if (reserveOut.sub(amountOut) >= sqrtK) {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
} else {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
if (reserveOut > sqrtK && boost0 != boost1) {
amountIn = sqrtK.sub(reserveIn).mul(10000);
amountOut = amountOut.sub(reserveOut.sub(sqrtK));
reserveOut = sqrtK;
reserveIn = sqrtK;
}
}
}
}
uint256 numerator = (reserveIn.add(artiLiqTerm)).mul(amountOut).mul(10000);
uint256 denominator = (reserveOut.add(artiLiqTerm)).sub(amountOut);
amountIn = (amountIn.add((numerator / denominator)).div(10000 - fee)).add(1);
}
function getAmountOutFeeOnTransfer(
address tokenIn,
address tokenOut,
address factory
) internal view returns (uint256, uint256) {
uint256 reserveIn;
uint256 reserveOut;
address pair;
bool isMatch;
{
(address token0, ) = sortTokens(tokenIn, tokenOut);
isMatch = tokenIn == token0;
(reserveIn, reserveOut, pair) = getReserves(factory, tokenIn, tokenOut);
}
uint256 amountOut;
uint256 artiLiqTerm;
uint256 amountInPostFee;
bool isXybk;
{
uint256 fee;
uint256 balanceIn = IERC20(tokenIn).balanceOf(address(pair));
require(balanceIn > reserveIn, 'ImpossibleLibrary: INSUFFICIENT_INPUT_AMOUNT');
IImpossiblePair.TradeState tradeState;
(fee, tradeState, isXybk) = IImpossiblePair(pair).getPairSettings();
require(
(tradeState == IImpossiblePair.TradeState.SELL_ALL) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_0 && !isMatch) ||
(tradeState == IImpossiblePair.TradeState.SELL_TOKEN_1 && isMatch),
'ImpossibleLibrary: TRADE_NOT_ALLOWED'
);
amountInPostFee = (balanceIn.sub(reserveIn)).mul(10000 - fee);
}
if (isXybk) {
(uint256 boost0, uint256 boost1) = IImpossiblePair(pair).calcBoost();
uint256 sqrtK = Math.sqrt(
xybkComputeK(boost0, boost1, isMatch ? reserveIn : reserveOut, isMatch ? reserveOut : reserveIn)
);
if (amountInPostFee.add(reserveIn.mul(10000)) >= sqrtK.mul(10000)) {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost0 : boost1, sqrtK);
if (reserveIn < sqrtK && boost0 != boost1) {
amountOut = reserveOut.sub(sqrtK);
amountInPostFee = amountInPostFee.sub(sqrtK.sub(reserveIn));
reserveOut = sqrtK;
reserveIn = sqrtK;
}
} else {
artiLiqTerm = calcArtiLiquidityTerm(isMatch ? boost1 : boost0, sqrtK);
}
}
uint256 numerator = amountInPostFee.mul(reserveOut.add(artiLiqTerm));
uint256 denominator = (reserveIn.add(artiLiqTerm)).mul(10000).add(amountInPostFee);
uint256 lastSwapAmountOut = numerator / denominator;
amountOut = (lastSwapAmountOut > reserveOut) ? reserveOut.add(amountOut) : lastSwapAmountOut.add(amountOut);
return isMatch ? (uint256(0), amountOut) : (amountOut, uint256(0));
}
function getAmountsOut(
address factory,
uint256 amountIn,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'ImpossibleLibrary: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
amounts[i + 1] = getAmountOut(amounts[i], path[i], path[i + 1], factory);
}
}
function getAmountsIn(
address factory,
uint256 amountOut,
address[] memory path
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, 'ImpossibleLibrary: INVALID_PATH');
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
amounts[i - 1] = getAmountIn(amounts[i], path[i - 1], path[i], factory);
}
}
}
文件 11 的 15:ImpossibleRouter.sol
pragma solidity =0.7.6;
pragma experimental ABIEncoderV2;
import './libraries/TransferHelper.sol';
import './libraries/ReentrancyGuard.sol';
import './libraries/ImpossibleLibrary.sol';
import './libraries/SafeMath.sol';
import './interfaces/IImpossibleSwapFactory.sol';
import './interfaces/IImpossibleRouterExtension.sol';
import './interfaces/IImpossibleRouter.sol';
import './interfaces/IERC20.sol';
import './interfaces/IWETH.sol';
import './interfaces/IImpossibleWrappedToken.sol';
import './interfaces/IImpossibleWrapperFactory.sol';
contract ImpossibleRouter is IImpossibleRouter, ReentrancyGuard {
using SafeMath for uint256;
address public immutable override factory;
address public immutable override wrapFactory;
address private utilitySettingAdmin;
address public override routerExtension;
address public override WETH;
modifier ensure(uint256 deadline) {
require(deadline >= block.timestamp, 'ImpossibleRouter: EXPIRED');
_;
}
constructor(
address _pairFactory,
address _wrapFactory,
address _utilitySettingAdmin
) {
factory = _pairFactory;
wrapFactory = _wrapFactory;
utilitySettingAdmin = _utilitySettingAdmin;
}
receive() external payable {
assert(msg.sender == WETH);
}
function setUtilities(address _WETH, address _routerExtension) public {
require(WETH == address(0x0) && routerExtension == address(0x0));
require(msg.sender == utilitySettingAdmin, 'IF: ?');
WETH = _WETH;
routerExtension = _routerExtension;
}
function wrapSafeTransfer(
address token,
address src,
address dst,
uint256 amt
) internal {
address underlying = IImpossibleWrapperFactory(wrapFactory).wrappedTokensToTokens(token);
if (underlying == address(0x0)) {
TransferHelper.safeTransferFrom(token, src, dst, amt);
} else {
uint256 underlyingAmt = IImpossibleWrappedToken(token).amtToUnderlyingAmt(amt);
TransferHelper.safeTransferFrom(underlying, src, address(this), underlyingAmt);
TransferHelper.safeApprove(underlying, token, underlyingAmt);
IImpossibleWrappedToken(token).deposit(dst, underlyingAmt);
}
}
function unwrapSafeTransfer(
address token,
address dst,
uint256 amt
) internal {
address underlying = IImpossibleWrapperFactory(wrapFactory).wrappedTokensToTokens(token);
if (underlying == address(0x0)) {
TransferHelper.safeTransfer(token, dst, amt);
} else {
IImpossibleWrappedToken(token).withdraw(dst, amt);
}
}
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
amounts = ImpossibleLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amounts[amounts.length - 1]);
}
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amountOut);
}
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsOut(factory, msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]));
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amounts[amounts.length - 1]);
}
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]);
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant returns (uint256[] memory amounts) {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
amounts = ImpossibleLibrary.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= msg.value, 'ImpossibleRouter: EXCESSIVE_INPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amounts[0]));
IImpossibleRouterExtension(routerExtension).swap(amounts, path);
unwrapSafeTransfer(path[path.length - 1], to, amountOut);
if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant {
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn);
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 balance = IERC20(path[path.length - 1]).balanceOf(address(this));
require(balance >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
unwrapSafeTransfer(path[path.length - 1], to, balance);
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable virtual override ensure(deadline) nonReentrant {
require(path[0] == WETH, 'ImpossibleRouter: INVALID_PATH');
uint256 amountIn = msg.value;
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn));
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 balance = IERC20(path[path.length - 1]).balanceOf(address(this));
require(balance >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
unwrapSafeTransfer(path[path.length - 1], to, balance);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external virtual override ensure(deadline) nonReentrant {
require(path[path.length - 1] == WETH, 'ImpossibleRouter: INVALID_PATH');
wrapSafeTransfer(path[0], msg.sender, ImpossibleLibrary.pairFor(factory, path[0], path[1]), amountIn);
IImpossibleRouterExtension(routerExtension).swapSupportingFeeOnTransferTokens(path);
uint256 amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, 'ImpossibleRouter: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).withdraw(amountOut);
TransferHelper.safeTransferETH(to, amountOut);
}
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
virtual
override
ensure(deadline)
nonReentrant
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
)
{
(amountA, amountB) = IImpossibleRouterExtension(routerExtension).addLiquidity(
tokenA,
tokenB,
amountADesired,
amountBDesired,
amountAMin,
amountBMin
);
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
wrapSafeTransfer(tokenA, msg.sender, pair, amountA);
wrapSafeTransfer(tokenB, msg.sender, pair, amountB);
liquidity = IImpossiblePair(pair).mint(to);
}
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
virtual
override
ensure(deadline)
nonReentrant
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
)
{
(amountToken, amountETH) = IImpossibleRouterExtension(routerExtension).addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
wrapSafeTransfer(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IImpossiblePair(pair).mint(to);
if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountA, uint256 amountB) {
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity);
(amountA, amountB) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
tokenA,
tokenB,
pair,
amountAMin,
amountBMin
);
unwrapSafeTransfer(tokenA, to, amountA);
unwrapSafeTransfer(tokenB, to, amountB);
}
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountToken, uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity);
(amountToken, amountETH) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
token,
WETH,
pair,
amountTokenMin,
amountETHMin
);
unwrapSafeTransfer(token, to, amountToken);
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountA, uint256 amountB) {
address pair = ImpossibleLibrary.pairFor(factory, tokenA, tokenB);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
return removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline);
}
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountToken, uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
(amountToken, amountETH) = removeLiquidityETH(token, liquidity, amountTokenMin, amountETHMin, to, deadline);
}
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) public virtual override ensure(deadline) nonReentrant returns (uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
IImpossiblePair(pair).transferFrom(msg.sender, pair, liquidity);
(, amountETH) = IImpossibleRouterExtension(routerExtension).removeLiquidity(
token,
WETH,
pair,
amountTokenMin,
amountETHMin
);
unwrapSafeTransfer(token, to, IERC20(token).balanceOf(address(this)));
IWETH(WETH).withdraw(amountETH);
TransferHelper.safeTransferETH(to, amountETH);
}
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external virtual override returns (uint256 amountETH) {
address pair = ImpossibleLibrary.pairFor(factory, token, WETH);
uint256 value = approveMax ? uint256(-1) : liquidity;
IImpossiblePair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
amountETH = removeLiquidityETHSupportingFeeOnTransferTokens(
token,
liquidity,
amountTokenMin,
amountETHMin,
to,
deadline
);
}
}
文件 12 的 15:Math.sol
pragma solidity =0.7.6;
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 13 的 15:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, 'ReentrancyGuard: reentrant call');
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 14 的 15:SafeMath.sol
pragma solidity =0.7.6;
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, 'SafeMath: division by zero');
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
}
文件 15 的 15:TransferHelper.sol
pragma solidity >=0.6.0;
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeApprove: approve failed'
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::safeTransfer: transfer failed'
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(
success && (data.length == 0 || abi.decode(data, (bool))),
'TransferHelper::transferFrom: transferFrom failed'
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
}
}
{
"compilationTarget": {
"contracts/ImpossibleRouter.sol": "ImpossibleRouter"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_pairFactory","type":"address"},{"internalType":"address","name":"_wrapFactory","type":"address"},{"internalType":"address","name":"_utilitySettingAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"amountADesired","type":"uint256"},{"internalType":"uint256","name":"amountBDesired","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountTokenDesired","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountTokenMin","type":"uint256"},{"internalType":"uint256","name":"amountETHMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","outputs":[{"internalType":"uint256","name":"amountETH","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"amountAMin","type":"uint256"},{"internalType":"uint256","name":"amountBMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerExtension","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_routerExtension","type":"address"}],"name":"setUtilities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrapFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]