编译器
0.8.19+commit.7dd6d404
文件 1 的 20:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 20:AerodromeCommands.sol
pragma solidity ^0.8.17;
library AerodromeCommands {
bytes1 internal constant FLAG_ALLOW_REVERT = 0x80;
bytes1 internal constant COMMAND_TYPE_MASK = 0x3f;
uint256 constant V3_SWAP_EXACT_IN = 0x00;
uint256 constant V3_SWAP_EXACT_OUT = 0x01;
uint256 constant PERMIT2_TRANSFER_FROM = 0x02;
uint256 constant PERMIT2_PERMIT_BATCH = 0x03;
uint256 constant SWEEP = 0x04;
uint256 constant TRANSFER = 0x05;
uint256 constant PAY_PORTION = 0x06;
uint256 constant FIRST_IF_BOUNDARY = 0x08;
uint256 constant V2_SWAP_EXACT_IN = 0x08;
uint256 constant V2_SWAP_EXACT_OUT = 0x09;
uint256 constant PERMIT2_PERMIT = 0x0a;
uint256 constant WRAP_ETH = 0x0b;
uint256 constant UNWRAP_WETH = 0x0c;
uint256 constant PERMIT2_TRANSFER_FROM_BATCH = 0x0d;
uint256 constant BALANCE_CHECK_ERC20 = 0x0e;
uint256 constant SECOND_IF_BOUNDARY = 0x10;
uint256 constant SEAPORT_V1_5 = 0x10;
uint256 constant LOOKS_RARE_V2 = 0x11;
uint256 constant NFTX = 0x12;
uint256 constant CRYPTOPUNKS = 0x13;
uint256 constant OWNER_CHECK_721 = 0x15;
uint256 constant OWNER_CHECK_1155 = 0x16;
uint256 constant SWEEP_ERC721 = 0x17;
uint256 constant THIRD_IF_BOUNDARY = 0x18;
uint256 constant X2Y2_721 = 0x18;
uint256 constant SUDOSWAP = 0x19;
uint256 constant NFT20 = 0x1a;
uint256 constant X2Y2_1155 = 0x1b;
uint256 constant FOUNDATION = 0x1c;
uint256 constant SWEEP_ERC1155 = 0x1d;
uint256 constant ELEMENT_MARKET = 0x1e;
uint256 constant FOURTH_IF_BOUNDARY = 0x20;
uint256 constant SEAPORT_V1_4 = 0x20;
uint256 constant EXECUTE_SUB_PLAN = 0x21;
uint256 constant APPROVE_ERC20 = 0x22;
}
文件 3 的 20:AerodromeDexAdapter.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol';
import '../interfaces/IAerodromeLpSugar.sol';
import '../interfaces/IAerodromeVoter.sol';
import '../interfaces/IAerodromePoolFactory.sol';
import '../interfaces/IAerodromeRouter.sol';
import '../interfaces/IAerodromeUniversalRouter.sol';
import '../interfaces/IV3TwapUtilities.sol';
import './UniswapDexAdapter.sol';
import { AerodromeCommands } from '../libraries/AerodromeCommands.sol';
contract AerodromeDexAdapter is UniswapDexAdapter {
using SafeERC20 for IERC20;
address constant AERO = 0x940181a94A35A4569E4529A3CDfB74e38FD98631;
address constant CL_FACTORY = 0x5e7BB104d84c7CB9B682AaC2F3d509f5F406809A;
address constant LP_SUGAR = 0xf739E2BC37fD5C1D3614dA67756dEEaEE0025667;
int24 constant TICK_SPACING = 200;
constructor(
IV3TwapUtilities _v3TwapUtilities,
address _v2Router,
address _v3Router
) UniswapDexAdapter(_v3TwapUtilities, _v2Router, _v3Router, true) {}
function WETH() external view virtual override returns (address) {
return address(IAerodromeRouter(V2_ROUTER).weth());
}
function getV3Pool(
address _token0,
address _token1,
int24 _tickSpacing
) external view override returns (address) {
return V3_TWAP_UTILS.getV3Pool(CL_FACTORY, _token0, _token1, _tickSpacing);
}
function getV3Pool(
address,
address,
uint24
) external view virtual override returns (address _p) {
_p;
require(false, 'I0');
}
function getV2Pool(
address _token0,
address _token1
) public view override returns (address) {
return
IAerodromePoolFactory(IAerodromeRouter(V2_ROUTER).defaultFactory())
.getPool(_token0, _token1, 0);
}
function createV2Pool(
address _token0,
address _token1
) external override returns (address) {
return
IAerodromePoolFactory(IAerodromeRouter(V2_ROUTER).defaultFactory())
.createPool(_token0, _token1, 0);
}
function swapV2Single(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external override returns (uint256 _amountOut) {
uint256 _outBefore = IERC20(_tokenOut).balanceOf(_recipient);
if (_amountIn == 0) {
_amountIn = IERC20(_tokenIn).balanceOf(address(this));
} else {
IERC20(_tokenIn).safeTransferFrom(_msgSender(), address(this), _amountIn);
}
IAerodromeRouter.Route[] memory _routes = new IAerodromeRouter.Route[](1);
_routes[0] = IAerodromeRouter.Route({
from: _tokenIn,
to: _tokenOut,
stable: false,
factory: IAerodromeRouter(V2_ROUTER).defaultFactory()
});
IERC20(_tokenIn).safeIncreaseAllowance(V2_ROUTER, _amountIn);
IAerodromeRouter(V2_ROUTER)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
_amountIn,
_amountOutMin,
_routes,
_recipient,
block.timestamp
);
return IERC20(_tokenOut).balanceOf(_recipient) - _outBefore;
}
function swapV3Single(
address _tokenIn,
address _tokenOut,
uint24,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external override returns (uint256 _amountOut) {
uint256 _outBefore = IERC20(_tokenOut).balanceOf(_recipient);
if (_amountIn == 0) {
_amountIn = IERC20(_tokenIn).balanceOf(address(this));
} else {
IERC20(_tokenIn).safeTransferFrom(_msgSender(), address(this), _amountIn);
}
IERC20(_tokenIn).safeIncreaseAllowance(V3_ROUTER, _amountIn);
bytes memory _commands = abi.encodePacked(
bytes1(uint8(AerodromeCommands.V3_SWAP_EXACT_IN))
);
bytes[] memory _inputs = new bytes[](1);
bytes memory _path = abi.encodePacked(_tokenIn, TICK_SPACING, _tokenOut);
_inputs[0] = abi.encode(_recipient, _amountIn, _amountOutMin, _path, true);
IAerodromeUniversalRouter(V3_ROUTER).execute(
_commands,
_inputs,
block.timestamp
);
return IERC20(_tokenOut).balanceOf(_recipient) - _outBefore;
}
function addLiquidity(
address _tokenA,
address _tokenB,
uint256 _amountADesired,
uint256 _amountBDesired,
uint256 _amountAMin,
uint256 _amountBMin,
address _to,
uint256 _deadline
) external virtual override {
uint256 _aBefore = IERC20(_tokenA).balanceOf(address(this));
uint256 _bBefore = IERC20(_tokenB).balanceOf(address(this));
IERC20(_tokenA).safeTransferFrom(
_msgSender(),
address(this),
_amountADesired
);
IERC20(_tokenB).safeTransferFrom(
_msgSender(),
address(this),
_amountBDesired
);
IERC20(_tokenA).safeIncreaseAllowance(V2_ROUTER, _amountADesired);
IERC20(_tokenB).safeIncreaseAllowance(V2_ROUTER, _amountBDesired);
IAerodromeRouter(V2_ROUTER).addLiquidity(
_tokenA,
_tokenB,
false,
_amountADesired,
_amountBDesired,
_amountAMin,
_amountBMin,
_to,
_deadline
);
if (IERC20(_tokenA).balanceOf(address(this)) > _aBefore) {
IERC20(_tokenA).safeTransfer(
_to,
IERC20(_tokenA).balanceOf(address(this)) - _aBefore
);
}
if (IERC20(_tokenB).balanceOf(address(this)) > _bBefore) {
IERC20(_tokenB).safeTransfer(
_to,
IERC20(_tokenB).balanceOf(address(this)) - _bBefore
);
}
}
function removeLiquidity(
address _tokenA,
address _tokenB,
uint256 _liquidity,
uint256 _amountAMin,
uint256 _amountBMin,
address _to,
uint256 _deadline
) external virtual override {
address _pool = IAerodromePoolFactory(
IAerodromeRouter(V2_ROUTER).defaultFactory()
).getPool(_tokenA, _tokenB, 0);
uint256 _lpBefore = IERC20(_pool).balanceOf(address(this));
IERC20(_pool).safeTransferFrom(_msgSender(), address(this), _liquidity);
IERC20(_pool).safeIncreaseAllowance(V2_ROUTER, _liquidity);
IAerodromeRouter(V2_ROUTER).removeLiquidity(
_tokenA,
_tokenB,
false,
_liquidity,
_amountAMin,
_amountBMin,
_to,
_deadline
);
if (IERC20(_pool).balanceOf(address(this)) > _lpBefore) {
IERC20(_pool).safeTransfer(
_to,
IERC20(_pool).balanceOf(address(this)) - _lpBefore
);
}
}
function extraRewardsHook(
address _token0,
address _token1
)
external
override
returns (address[] memory _tokens, uint256[] memory _amounts)
{
_tokens[0] = AERO;
uint256 _aeroBefore = IERC20(AERO).balanceOf(address(this));
address _pool = getV2Pool(_token0, _token1);
IAerodromeVoter _voter = IAerodromeVoter(
IAerodromeLpSugar(LP_SUGAR).voter()
);
address[] memory _gauges = new address[](1);
_gauges[0] = _voter.gauges(_pool);
_voter.claimRewards(_gauges);
_amounts[0] = IERC20(AERO).balanceOf(address(this)) - _aeroBefore;
}
}
文件 4 的 20:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 5 的 20:IAerodromeLpSugar.sol
pragma solidity ^0.8.19;
interface IAerodromeLpSugar {
function voter() external view returns (address);
}
文件 6 的 20:IAerodromePoolFactory.sol
pragma solidity ^0.8.19;
interface IAerodromePoolFactory {
event SetFeeManager(address feeManager);
event SetPauser(address pauser);
event SetPauseState(bool state);
event SetVoter(address voter);
event PoolCreated(
address indexed token0,
address indexed token1,
bool indexed stable,
address pool,
uint256
);
event SetCustomFee(address indexed pool, uint256 fee);
error FeeInvalid();
error FeeTooHigh();
error InvalidPool();
error NotFeeManager();
error NotPauser();
error NotVoter();
error PoolAlreadyExists();
error SameAddress();
error ZeroFee();
error ZeroAddress();
function allPoolsLength() external view returns (uint256);
function isPool(address pool) external view returns (bool);
function getPool(
address tokenA,
address tokenB,
bool stable
) external view returns (address);
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address);
function setVoter(address _voter) external;
function setPauser(address _pauser) external;
function setPauseState(bool _state) external;
function setFeeManager(address _feeManager) external;
function setFee(bool _stable, uint256 _fee) external;
function setCustomFee(address _pool, uint256 _fee) external;
function getFee(address _pool, bool _stable) external view returns (uint256);
function createPool(
address tokenA,
address tokenB,
bool stable
) external returns (address pool);
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external returns (address pool);
function isPaused() external view returns (bool);
function voter() external view returns (address);
function implementation() external view returns (address);
}
文件 7 的 20:IAerodromeRouter.sol
pragma solidity ^0.8.0;
import { IWETH } from './IWETH.sol';
interface IAerodromeRouter {
struct Route {
address from;
address to;
bool stable;
address factory;
}
error ETHTransferFailed();
error Expired();
error InsufficientAmount();
error InsufficientAmountA();
error InsufficientAmountB();
error InsufficientAmountADesired();
error InsufficientAmountBDesired();
error InsufficientAmountAOptimal();
error InsufficientLiquidity();
error InsufficientOutputAmount();
error InvalidAmountInForETHDeposit();
error InvalidTokenInForETHDeposit();
error InvalidPath();
error InvalidRouteA();
error InvalidRouteB();
error OnlyWETH();
error PoolDoesNotExist();
error PoolFactoryDoesNotExist();
error SameAddresses();
error ZeroAddress();
function factoryRegistry() external view returns (address);
function defaultFactory() external view returns (address);
function voter() external view returns (address);
function weth() external view returns (IWETH);
function ETHER() external view returns (address);
struct Zap {
address tokenA;
address tokenB;
bool stable;
address factory;
uint256 amountOutMinA;
uint256 amountOutMinB;
uint256 amountAMin;
uint256 amountBMin;
}
function sortTokens(
address tokenA,
address tokenB
) external pure returns (address token0, address token1);
function poolFor(
address tokenA,
address tokenB,
bool stable,
address _factory
) external view returns (address pool);
function getReserves(
address tokenA,
address tokenB,
bool stable,
address _factory
) external view returns (uint256 reserveA, uint256 reserveB);
function getAmountsOut(
uint256 amountIn,
Route[] memory routes
) external view returns (uint256[] memory amounts);
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
address _factory,
uint256 amountADesired,
uint256 amountBDesired
) external view returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function quoteRemoveLiquidity(
address tokenA,
address tokenB,
bool stable,
address _factory,
uint256 liquidity
) external view returns (uint256 amountA, uint256 amountB);
function addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function addLiquidityETH(
address token,
bool stable,
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,
bool stable,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
bool stable,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
bool stable,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function UNSAFE_swapExactTokensForTokens(
uint256[] memory amounts,
Route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) external;
function zapIn(
address tokenIn,
uint256 amountInA,
uint256 amountInB,
Zap calldata zapInPool,
Route[] calldata routesA,
Route[] calldata routesB,
address to,
bool stake
) external payable returns (uint256 liquidity);
function zapOut(
address tokenOut,
uint256 liquidity,
Zap calldata zapOutPool,
Route[] calldata routesA,
Route[] calldata routesB
) external;
function generateZapInParams(
address tokenA,
address tokenB,
bool stable,
address _factory,
uint256 amountInA,
uint256 amountInB,
Route[] calldata routesA,
Route[] calldata routesB
)
external
view
returns (
uint256 amountOutMinA,
uint256 amountOutMinB,
uint256 amountAMin,
uint256 amountBMin
);
function generateZapOutParams(
address tokenA,
address tokenB,
bool stable,
address _factory,
uint256 liquidity,
Route[] calldata routesA,
Route[] calldata routesB
)
external
view
returns (
uint256 amountOutMinA,
uint256 amountOutMinB,
uint256 amountAMin,
uint256 amountBMin
);
function quoteStableLiquidityRatio(
address tokenA,
address tokenB,
address factory
) external view returns (uint256 ratio);
}
文件 8 的 20:IAerodromeUniversalRouter.sol
pragma solidity ^0.8.17;
interface IAerodromeUniversalRouter {
function execute(
bytes calldata commands,
bytes[] calldata inputs,
uint256 deadline
) external payable;
}
文件 9 的 20:IAerodromeVoter.sol
pragma solidity ^0.8.19;
interface IAerodromeVoter {
function gauges(address pool) external view returns (address);
function claimRewards(address[] memory _gauges) external;
}
文件 10 的 20:IDexAdapter.sol
pragma solidity ^0.8.19;
interface IDexAdapter {
function ASYNC_INITIALIZE() external view returns (bool);
function V2_ROUTER() external view returns (address);
function V3_ROUTER() external view returns (address);
function WETH() external view returns (address);
function getV3Pool(
address _token0,
address _token1,
int24 _tickSpacing
) external view returns (address _pool);
function getV3Pool(
address _token0,
address _token1,
uint24 _poolFee
) external view returns (address _pool);
function getV2Pool(
address _token0,
address _token1
) external view returns (address _pool);
function createV2Pool(
address _token0,
address _token1
) external returns (address _pool);
function swapV2Single(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function swapV3Single(
address _tokenIn,
address _tokenOut,
uint24 _fee,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external returns (uint256 _amountOut);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external;
function extraRewardsHook(
address _token0,
address _token1
) external returns (address[] memory tokens, uint256[] memory amounts);
}
文件 11 的 20:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 12 的 20:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 13 的 20:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 14 的 20:ISwapRouter02.sol
pragma solidity ^0.8.19;
interface ISwapRouter02 {
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);
}
文件 15 的 20:IUniswapV2Factory.sol
pragma solidity ^0.8.19;
interface IUniswapV2Factory {
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
}
文件 16 的 20:IUniswapV2Router02.sol
pragma solidity ^0.8.19;
interface IUniswapV2Router02 {
function factory() external view returns (address);
function WETH() external view returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 17 的 20:IV3TwapUtilities.sol
pragma solidity ^0.8.19;
interface IV3TwapUtilities {
function getV3Pool(
address v3Factory,
address token0,
address token1
) external view returns (address);
function getV3Pool(
address v3Factory,
address token0,
address token1,
uint24 poolFee
) external view returns (address);
function getV3Pool(
address v3Factory,
address token0,
address token1,
int24 tickSpacing
) external view returns (address);
function getPoolPriceUSDX96(
address pricePool,
address nativeStablePool,
address WETH9
) external view returns (uint256);
function sqrtPriceX96FromPoolAndInterval(
address pool
) external view returns (uint160);
function priceX96FromSqrtPriceX96(
uint160 sqrtPriceX96
) external pure returns (uint256);
}
文件 18 的 20:IWETH.sol
pragma solidity ^0.8.19;
interface IWETH {
function deposit() external payable;
function withdraw(uint256 _amount) external;
}
文件 19 的 20:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 20 的 20:UniswapDexAdapter.sol
pragma solidity ^0.8.19;
import '@openzeppelin/contracts/utils/Context.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol';
import '../interfaces/IDexAdapter.sol';
import '../interfaces/ISwapRouter02.sol';
import '../interfaces/IUniswapV2Factory.sol';
import '../interfaces/IUniswapV2Router02.sol';
import '../interfaces/IV3TwapUtilities.sol';
contract UniswapDexAdapter is IDexAdapter, Context {
using SafeERC20 for IERC20;
IV3TwapUtilities public immutable V3_TWAP_UTILS;
address public immutable override V2_ROUTER;
address public immutable override V3_ROUTER;
bool public immutable override ASYNC_INITIALIZE;
constructor(
IV3TwapUtilities _v3TwapUtilities,
address _v2Router,
address _v3Router,
bool _asyncInit
) {
V3_TWAP_UTILS = _v3TwapUtilities;
V2_ROUTER = _v2Router;
V3_ROUTER = _v3Router;
ASYNC_INITIALIZE = _asyncInit;
}
function WETH() external view virtual override returns (address) {
return IUniswapV2Router02(V2_ROUTER).WETH();
}
function getV3Pool(
address,
address,
int24
) external view virtual override returns (address _p) {
_p;
require(false, 'I0');
}
function getV3Pool(
address _token0,
address _token1,
uint24 _poolFee
) external view virtual override returns (address) {
return
V3_TWAP_UTILS.getV3Pool(
IPeripheryImmutableState(V3_ROUTER).factory(),
_token0,
_token1,
_poolFee
);
}
function getV2Pool(
address _token0,
address _token1
) external view virtual override returns (address) {
return
IUniswapV2Factory(IUniswapV2Router02(V2_ROUTER).factory()).getPair(
_token0,
_token1
);
}
function createV2Pool(
address _token0,
address _token1
) external virtual override returns (address) {
return
IUniswapV2Factory(IUniswapV2Router02(V2_ROUTER).factory()).createPair(
_token0,
_token1
);
}
function swapV2Single(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external virtual override returns (uint256 _amountOut) {
uint256 _outBefore = IERC20(_tokenOut).balanceOf(_recipient);
if (_amountIn == 0) {
_amountIn = IERC20(_tokenIn).balanceOf(address(this));
} else {
IERC20(_tokenIn).safeTransferFrom(_msgSender(), address(this), _amountIn);
}
address[] memory _path = new address[](2);
_path[0] = _tokenIn;
_path[1] = _tokenOut;
IERC20(_tokenIn).safeIncreaseAllowance(V2_ROUTER, _amountIn);
IUniswapV2Router02(V2_ROUTER)
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
_amountIn,
_amountOutMin,
_path,
_recipient,
block.timestamp
);
return IERC20(_tokenOut).balanceOf(_recipient) - _outBefore;
}
function swapV3Single(
address _tokenIn,
address _tokenOut,
uint24 _fee,
uint256 _amountIn,
uint256 _amountOutMin,
address _recipient
) external virtual override returns (uint256 _amountOut) {
uint256 _outBefore = IERC20(_tokenOut).balanceOf(_recipient);
if (_amountIn == 0) {
_amountIn = IERC20(_tokenIn).balanceOf(address(this));
} else {
IERC20(_tokenIn).safeTransferFrom(_msgSender(), address(this), _amountIn);
}
IERC20(_tokenIn).safeIncreaseAllowance(V3_ROUTER, _amountIn);
ISwapRouter02(V3_ROUTER).exactInputSingle(
ISwapRouter02.ExactInputSingleParams({
tokenIn: _tokenIn,
tokenOut: _tokenOut,
fee: _fee,
recipient: _recipient,
amountIn: _amountIn,
amountOutMinimum: _amountOutMin,
sqrtPriceLimitX96: 0
})
);
return IERC20(_tokenOut).balanceOf(_recipient) - _outBefore;
}
function addLiquidity(
address _tokenA,
address _tokenB,
uint256 _amountADesired,
uint256 _amountBDesired,
uint256 _amountAMin,
uint256 _amountBMin,
address _to,
uint256 _deadline
) external virtual override {
uint256 _aBefore = IERC20(_tokenA).balanceOf(address(this));
uint256 _bBefore = IERC20(_tokenB).balanceOf(address(this));
IERC20(_tokenA).safeTransferFrom(
_msgSender(),
address(this),
_amountADesired
);
IERC20(_tokenB).safeTransferFrom(
_msgSender(),
address(this),
_amountBDesired
);
IERC20(_tokenA).safeIncreaseAllowance(V2_ROUTER, _amountADesired);
IERC20(_tokenB).safeIncreaseAllowance(V2_ROUTER, _amountBDesired);
IUniswapV2Router02(V2_ROUTER).addLiquidity(
_tokenA,
_tokenB,
_amountADesired,
_amountBDesired,
_amountAMin,
_amountBMin,
_to,
_deadline
);
if (IERC20(_tokenA).balanceOf(address(this)) > _aBefore) {
IERC20(_tokenA).safeTransfer(
_to,
IERC20(_tokenA).balanceOf(address(this)) - _aBefore
);
}
if (IERC20(_tokenB).balanceOf(address(this)) > _bBefore) {
IERC20(_tokenB).safeTransfer(
_to,
IERC20(_tokenB).balanceOf(address(this)) - _bBefore
);
}
}
function removeLiquidity(
address _tokenA,
address _tokenB,
uint256 _liquidity,
uint256 _amountAMin,
uint256 _amountBMin,
address _to,
uint256 _deadline
) external virtual override {
address _pool = IUniswapV2Factory(IUniswapV2Router02(V2_ROUTER).factory())
.getPair(_tokenA, _tokenB);
uint256 _lpBefore = IERC20(_pool).balanceOf(address(this));
IERC20(_pool).safeTransferFrom(_msgSender(), address(this), _liquidity);
IERC20(_pool).safeIncreaseAllowance(V2_ROUTER, _liquidity);
IUniswapV2Router02(V2_ROUTER).removeLiquidity(
_tokenA,
_tokenB,
_liquidity,
_amountAMin,
_amountBMin,
_to,
_deadline
);
if (IERC20(_pool).balanceOf(address(this)) > _lpBefore) {
IERC20(_pool).safeTransfer(
_to,
IERC20(_pool).balanceOf(address(this)) - _lpBefore
);
}
}
function extraRewardsHook(
address,
address
)
external
virtual
override
returns (address[] memory _t, uint256[] memory _a)
{
_t;
_a;
}
}
{
"compilationTarget": {
"contracts/dex/AerodromeDexAdapter.sol": "AerodromeDexAdapter"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IV3TwapUtilities","name":"_v3TwapUtilities","type":"address"},{"internalType":"address","name":"_v2Router","type":"address"},{"internalType":"address","name":"_v3Router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ASYNC_INITIALIZE","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V2_ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V3_ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V3_TWAP_UTILS","outputs":[{"internalType":"contract IV3TwapUtilities","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"createV2Pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"extraRewardsHook","outputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"getV2Pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"int24","name":"_tickSpacing","type":"int24"}],"name":"getV3Pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint24","name":"","type":"uint24"}],"name":"getV3Pool","outputs":[{"internalType":"address","name":"_p","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":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"swapV2Single","outputs":[{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint24","name":"","type":"uint24"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"swapV3Single","outputs":[{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]