编译器
0.8.18+commit.87f61d96
文件 1 的 18:Constants.sol
pragma solidity ^0.8.0;
library Constants {
address public constant UNISWAP_V3_FACTORY_ADDRESS =
address(0x1F98431c8aD98523631AE4a59f267346ea31F984);
address public constant NONFUNGIBLE_POSITION_MANAGER_ADDRESS =
address(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
address public constant SWAP_ROUTER_ADDRESS =
address(0xE592427A0AEce92De3Edee1F18E0157C05861564);
address public constant WETH_ADDRESS =
address(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);
address public constant ARB_ADDRESS =
address(0x912CE59144191C1204E64559FE8253a0e49E6548);
address public constant WBTC_ADDRESS =
address(0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f);
address public constant USDC_ADDRESS =
address(0xaf88d065e77c8cC2239327C5EDb3A432268e5831);
address public constant USDCE_ADDRESS =
address(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8);
address public constant USDT_ADDRESS =
address(0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9);
address public constant RDNT_ADDRESS =
address(0x3082CC23568eA640225c2467653dB90e9250AaA0);
address public constant LINK_ADDRESS =
address(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4);
address public constant BLACK_HOLE_ADDRESS =
address(0x000000000000000000000000000000000000dEaD);
}
文件 2 的 18: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;
}
}
文件 3 的 18: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);
}
文件 4 的 18:IERC20Querier.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IERC20Querier is IERC20 {
function decimals() external view returns (uint256);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
}
文件 5 的 18:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(
ExactInputSingleParams calldata params
) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(
ExactInputParams calldata params
) external payable returns (uint256 amountOut);
}
文件 6 的 18:IUniswapV3Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV3Factory {
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
}
文件 7 的 18:IUniswapV3Pool.sol
pragma solidity >=0.5.0;
interface IUniswapV3Pool {
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function tickSpacing() external view returns (int24);
}
文件 8 的 18:IWETH9.sol
pragma solidity ^0.8.0;
interface IWETH9 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 9 的 18:IZap.sol
pragma solidity ^0.8.0;
interface IZap {
function slippageToleranceNumerator() external view returns (uint24);
function getSwapInfo(
address inputToken,
address outputToken
)
external
view
returns (
bool isPathDefined,
address[] memory swapPathArray,
uint24[] memory swapTradeFeeArray
);
function getTokenExchangeRate(
address inputToken,
address outputToken
)
external
view
returns (
address token0,
address token1,
uint256 tokenPriceWith18Decimals
);
function getMinimumSwapOutAmount(
address inputToken,
address outputToken,
uint256 inputAmount
) external view returns (uint256 minimumSwapOutAmount);
function swapToken(
bool isETH,
address inputToken,
address outputToken,
uint256 inputAmount,
address recipient
) external payable returns (uint256 outputAmount);
function swapTokenWithMinimumOutput(
bool isETH,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 minimumSwapOutAmount,
address recipient
) external payable returns (uint256 outputAmount);
}
文件 10 的 18:IZapEvent.sol
pragma solidity ^0.8.0;
interface IZapEvent {
event UpdateSlippageTolerance(uint24 slippageTolerance);
event UpdateSwapTradeFee(
address indexed inputToken,
address indexed outputToken,
uint24 swapTradeFee
);
event UpdateSwapPath(
address indexed inputToken,
address indexed outputToken,
address[] newSwapPath
);
event SingleSwap(
address indexed recipient,
bool isETH,
address inputToken,
uint256 inputAmount,
address outputToken,
uint256 outputAmount,
address[] swapPath,
uint24[] swapTradeFee
);
event MultiSwap(
address indexed recipient,
bool isETH,
address inputToken,
uint256 inputAmount,
address outputToken,
uint256 outputAmount,
address[] swapPath,
uint24[] swapTradeFee
);
}
文件 11 的 18:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 12 的 18:ParameterVerificationHelper.sol
pragma solidity ^0.8.0;
library ParameterVerificationHelper {
function verifyNotZeroAddress(address inputAddress) internal pure {
require(inputAddress != address(0), "input zero address");
}
function verifyGreaterThanZero(uint256 inputNumber) internal pure {
require(inputNumber > 0, "input 0");
}
function verifyGreaterThanZero(int24 inputNumber) internal pure {
require(inputNumber > 0, "input 0");
}
function verifyGreaterThanOne(int24 inputNumber) internal pure {
require(inputNumber > 1, "input <= 1");
}
function verifyGreaterThanOrEqualToZero(int24 inputNumber) internal pure {
require(inputNumber >= 0, "input less than 0");
}
function verifyPairTokensHaveWeth(
address token0Address,
address token1Address,
address wethAddress
) internal pure {
require(
token0Address == wethAddress || token1Address == wethAddress,
"pair token not have WETH"
);
}
function verifyMsgValueEqualsInputAmount(
uint256 inputAmount
) internal view {
require(msg.value == inputAmount, "msg.value != inputAmount");
}
function verifyPairTokensHaveInputToken(
address token0Address,
address token1Address,
address inputToken
) internal pure {
require(
token0Address == inputToken || token1Address == inputToken,
"pair token not have inputToken"
);
}
}
文件 13 的 18:PoolHelper.sol
pragma solidity ^0.8.0;
import "../interfaces/external/IERC20Querier.sol";
import "../interfaces/uniswapV3/IUniswapV3Factory.sol";
import "../interfaces/uniswapV3/IUniswapV3Pool.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
library PoolHelper {
using SafeMath for uint256;
function getPoolAddress(
address uniswapV3FactoryAddress,
address tokenA,
address tokenB,
uint24 poolFee
) internal view returns (address poolAddress) {
return
IUniswapV3Factory(uniswapV3FactoryAddress).getPool(
tokenA,
tokenB,
poolFee
);
}
function getPoolInfo(
address poolAddress
)
internal
view
returns (
address token0,
address token1,
uint24 poolFee,
int24 tick,
uint160 sqrtPriceX96,
uint256 decimal0,
uint256 decimal1
)
{
(sqrtPriceX96, tick, , , , , ) = IUniswapV3Pool(poolAddress).slot0();
token0 = IUniswapV3Pool(poolAddress).token0();
token1 = IUniswapV3Pool(poolAddress).token1();
poolFee = IUniswapV3Pool(poolAddress).fee();
decimal0 = IERC20Querier(token0).decimals();
decimal1 = IERC20Querier(token1).decimals();
}
function getTokenPriceWithDecimalsByPool(
address poolAddress,
uint256 decimalPrecision
) internal view returns (uint256 tokenPriceWithDecimals) {
(
,
,
,
,
uint160 sqrtPriceX96,
uint256 decimal0,
uint256 decimal1
) = getPoolInfo(poolAddress);
uint256 scaledPriceX96 = uint256(sqrtPriceX96)
.mul(10 ** decimalPrecision)
.div(2 ** 96);
uint256 tokenPriceWithoutDecimalAdj = scaledPriceX96.mul(
scaledPriceX96
);
uint256 decimalAdj = decimalPrecision.add(decimal1).sub(decimal0);
uint256 result = tokenPriceWithoutDecimalAdj.div(10 ** decimalAdj);
require(result > 0, "token price too small");
tokenPriceWithDecimals = result;
}
function getTokenDecimalAdjustment(
address token
) internal view returns (uint256 decimalAdjustment) {
uint256 tokenDecimalStandard = 18;
uint256 decimal = IERC20Querier(token).decimals();
return tokenDecimalStandard.sub(decimal);
}
}
文件 14 的 18:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 15 的 18:TransferHelper.sol
pragma solidity >=0.6.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
library TransferHelper {
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
IERC20.transferFrom.selector,
from,
to,
value
)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"STF"
);
}
function safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"ST"
);
}
function safeApprove(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.approve.selector, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"SA"
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "STE");
}
}
文件 16 的 18:Zap.sol
pragma solidity ^0.8.0;
import "./interfaces/external/IERC20Querier.sol";
import "./interfaces/external/IWETH9.sol";
import "./interfaces/IZap.sol";
import "./interfaces/IZapEvent.sol";
import "./interfaces/uniswapV3/ISwapRouter.sol";
import "./libraries/constants/ZapConstants.sol";
import "./libraries/constants/Constants.sol";
import "./libraries/uniswapV3/TransferHelper.sol";
import "./libraries/ParameterVerificationHelper.sol";
import "./libraries/PoolHelper.sol";
import "./ZapInitializer.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract Zap is IZap, IZapEvent, Ownable, ZapInitializer {
using SafeMath for uint256;
uint24 public override slippageToleranceNumerator;
address public WETH;
constructor(uint24 _slippageToleranceNumerator) {
initializeSwapTradeFeeNumerator();
initializeSwapPath();
slippageToleranceNumerator = _slippageToleranceNumerator;
WETH = Constants.WETH_ADDRESS;
}
function getSwapInfo(
address inputToken,
address outputToken
)
public
view
override
returns (
bool isPathDefined,
address[] memory swapPathArray,
uint24[] memory swapTradeFeeArray
)
{
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
require(inputToken != outputToken, "inputToken == outputToken");
address[] memory _swapPathArray = swapPath[inputToken][outputToken];
uint256 pathLength = _swapPathArray.length;
if (pathLength >= 2) {
bool _isPathDefined = true;
uint24[] memory _swapTradeFeeArray = new uint24[](pathLength - 1);
for (uint i = 0; i < (pathLength - 1); i++) {
uint24 tradeFee = swapTradeFeeNumerator[_swapPathArray[i]][
_swapPathArray[i + 1]
];
if (tradeFee == 0) {
_isPathDefined = false;
}
_swapTradeFeeArray[i] = tradeFee;
}
return (_isPathDefined, _swapPathArray, _swapTradeFeeArray);
} else {
return (false, new address[](0), new uint24[](0));
}
}
function setSlippageToleranceNumerator(
uint24 slippageTolerance
) public onlyOwner {
ParameterVerificationHelper.verifyGreaterThanZero(slippageTolerance);
require(
slippageTolerance < ZapConstants.SLIPPAGE_TOLERANCE_DENOMINATOR,
"slippageTolerance too big"
);
slippageToleranceNumerator = slippageTolerance;
emit UpdateSlippageTolerance(slippageTolerance);
}
function setSwapTradeFeeNumerator(
address inputToken,
address outputToken,
uint24 swapTradeFee
) public onlyOwner {
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
ParameterVerificationHelper.verifyGreaterThanZero(swapTradeFee);
require(inputToken != outputToken, "inputToken == outputToken");
address poolAddress = PoolHelper.getPoolAddress(
Constants.UNISWAP_V3_FACTORY_ADDRESS,
inputToken,
outputToken,
swapTradeFee
);
require(poolAddress != address(0), "pool not exist");
swapTradeFeeNumerator[inputToken][outputToken] = swapTradeFee;
emit UpdateSwapTradeFee(inputToken, outputToken, swapTradeFee);
}
function setSwapPath(
address inputToken,
address outputToken,
address[] memory newSwapPath
) public onlyOwner {
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
uint256 pathLength = newSwapPath.length;
for (uint i = 0; i < pathLength; i++) {
ParameterVerificationHelper.verifyNotZeroAddress(newSwapPath[i]);
}
require(inputToken != outputToken, "inputToken == outputToken");
require(pathLength >= 2, "path too short");
require(newSwapPath[0] == inputToken, "path not start from inputToken");
require(
newSwapPath[(pathLength - 1)] == outputToken,
"path not end with outputToken"
);
for (uint i = 0; i < (pathLength - 1); i++) {
uint24 tradeFee = swapTradeFeeNumerator[newSwapPath[i]][
newSwapPath[i + 1]
];
require(tradeFee != 0, "tradefee not defined");
}
swapPath[inputToken][outputToken] = newSwapPath;
emit UpdateSwapPath(inputToken, outputToken, newSwapPath);
}
function getTokenExchangeRate(
address inputToken,
address outputToken
)
public
view
override
returns (
address token0,
address token1,
uint256 tokenPriceWith18Decimals
)
{
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
require(inputToken != outputToken, "inputToken == outputToken");
uint24 tradeFee = swapTradeFeeNumerator[inputToken][outputToken];
require(tradeFee != 0, "tradeFee not define");
address poolAddress = PoolHelper.getPoolAddress(
Constants.UNISWAP_V3_FACTORY_ADDRESS,
inputToken,
outputToken,
tradeFee
);
require(poolAddress != address(0), "pool not exist");
(token0, token1, , , , , ) = PoolHelper.getPoolInfo(poolAddress);
tokenPriceWith18Decimals = PoolHelper.getTokenPriceWithDecimalsByPool(
poolAddress,
ZapConstants.DECIMALS_PRECISION
);
}
function getMinimumSwapOutAmount(
address inputToken,
address outputToken,
uint256 inputAmount
) public view override returns (uint256 minimumSwapOutAmount) {
uint256 estimateSwapOutAmount = getEstimateSwapOutAmount(
inputToken,
outputToken,
inputAmount
);
uint256 _minimumSwapOutAmount = estimateSwapOutAmount
.mul(
uint256(ZapConstants.SLIPPAGE_TOLERANCE_DENOMINATOR).sub(
slippageToleranceNumerator
)
)
.div(ZapConstants.SLIPPAGE_TOLERANCE_DENOMINATOR);
minimumSwapOutAmount = _minimumSwapOutAmount;
}
function getEstimateSwapOutAmount(
address inputToken,
address outputToken,
uint256 inputAmount
) public view returns (uint256 estimateSwapOutAmount) {
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
ParameterVerificationHelper.verifyGreaterThanZero(inputAmount);
require(
slippageToleranceNumerator > 0,
"slippageToleranceNumerator is 0"
);
require(inputToken != outputToken, "inputToken == outputToken");
(
bool isPathDefined,
address[] memory swapPathArray,
uint24[] memory swapTradeFeeArray
) = getSwapInfo(inputToken, outputToken);
require(isPathDefined == true, "path not define");
uint256 pathLength = swapPathArray.length;
uint256 calcAmount = inputAmount.mul(
10 ** (PoolHelper.getTokenDecimalAdjustment(inputToken))
);
for (uint i = 0; i < (pathLength - 1); i++) {
address tokenIn = swapPathArray[i];
address tokenOut = swapPathArray[i + 1];
(
address token0,
address token1,
uint256 tokenPriceWith18Decimals
) = getTokenExchangeRate(tokenIn, tokenOut);
calcAmount = calcAmount
.mul(
uint256(ZapConstants.SWAP_TRADE_FEE_DENOMINATOR).sub(
swapTradeFeeArray[i]
)
)
.div(ZapConstants.SWAP_TRADE_FEE_DENOMINATOR);
require(tokenIn == token0 || tokenIn == token1);
if (tokenIn == token0) {
calcAmount = calcAmount.mul(tokenPriceWith18Decimals).div(
10 ** ZapConstants.DECIMALS_PRECISION
);
} else {
calcAmount = calcAmount
.mul(10 ** ZapConstants.DECIMALS_PRECISION)
.div(tokenPriceWith18Decimals);
}
}
estimateSwapOutAmount = calcAmount.div(
10 ** (PoolHelper.getTokenDecimalAdjustment(outputToken))
);
}
function swapToken(
bool isETH,
address inputToken,
address outputToken,
uint256 inputAmount,
address recipient
) public payable override returns (uint256 outputAmount) {
uint256 minimumSwapOutAmount = getMinimumSwapOutAmount(
inputToken,
outputToken,
inputAmount
);
outputAmount = swapTokenWithMinimumOutput(
isETH,
inputToken,
outputToken,
inputAmount,
minimumSwapOutAmount,
recipient
);
}
function swapTokenWithMinimumOutput(
bool isETH,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 minimumSwapOutAmount,
address recipient
) public payable override returns (uint256 outputAmount) {
ParameterVerificationHelper.verifyNotZeroAddress(inputToken);
ParameterVerificationHelper.verifyNotZeroAddress(outputToken);
ParameterVerificationHelper.verifyNotZeroAddress(recipient);
ParameterVerificationHelper.verifyGreaterThanZero(inputAmount);
require(inputToken != outputToken, "inputToken == outputToken");
(
bool isPathDefined,
address[] memory swapPathArray,
uint24[] memory swapTradeFeeArray
) = getSwapInfo(inputToken, outputToken);
require(isPathDefined == true, "path not define");
if (isETH) {
ParameterVerificationHelper.verifyMsgValueEqualsInputAmount(
inputAmount
);
require(
inputToken == WETH,
"input ETH must have swap path from WETH"
);
IWETH9(WETH).deposit{value: inputAmount}();
} else {
require(
IERC20Querier(inputToken).allowance(
msg.sender,
address(this)
) >= inputAmount,
"allowance insufficient"
);
TransferHelper.safeTransferFrom(
inputToken,
msg.sender,
address(this),
inputAmount
);
}
TransferHelper.safeApprove(
inputToken,
Constants.SWAP_ROUTER_ADDRESS,
inputAmount
);
uint256 pathLength = swapPathArray.length;
if (pathLength == 2) {
outputAmount = ISwapRouter(Constants.SWAP_ROUTER_ADDRESS)
.exactInputSingle(
ISwapRouter.ExactInputSingleParams(
inputToken,
outputToken,
swapTradeFeeArray[0],
recipient,
block.timestamp.add(transactionDeadlineDuration),
inputAmount,
minimumSwapOutAmount,
0
)
);
emit SingleSwap(
recipient,
isETH,
inputToken,
inputAmount,
outputToken,
outputAmount,
swapPathArray,
swapTradeFeeArray
);
} else {
bytes memory path = abi.encodePacked(swapPathArray[0]);
for (uint i = 0; i < (pathLength - 1); i++) {
path = abi.encodePacked(
path,
swapTradeFeeArray[i],
swapPathArray[i + 1]
);
}
outputAmount = ISwapRouter(Constants.SWAP_ROUTER_ADDRESS)
.exactInput(
ISwapRouter.ExactInputParams(
path,
recipient,
block.timestamp.add(transactionDeadlineDuration),
inputAmount,
minimumSwapOutAmount
)
);
emit MultiSwap(
recipient,
isETH,
inputToken,
inputAmount,
outputToken,
outputAmount,
swapPathArray,
swapTradeFeeArray
);
}
}
}
文件 17 的 18:ZapConstants.sol
pragma solidity ^0.8.0;
library ZapConstants {
uint256 public constant DECIMALS_PRECISION = 18;
uint24 public constant SLIPPAGE_TOLERANCE_DENOMINATOR = 1000000;
uint24 public constant SWAP_TRADE_FEE_DENOMINATOR = 1000000;
}
文件 18 的 18:ZapInitializer.sol
pragma solidity ^0.8.0;
import "./libraries/constants/Constants.sol";
contract ZapInitializer {
uint256 public transactionDeadlineDuration = 300;
mapping(address => mapping(address => address[])) internal swapPath;
mapping(address => mapping(address => uint24))
internal swapTradeFeeNumerator;
function initializeSwapTradeFeeNumerator() internal {
address WETH = Constants.WETH_ADDRESS;
address ARB = Constants.ARB_ADDRESS;
address WBTC = Constants.WBTC_ADDRESS;
address USDC = Constants.USDC_ADDRESS;
address USDCE = Constants.USDCE_ADDRESS;
address USDT = Constants.USDT_ADDRESS;
address RDNT = Constants.RDNT_ADDRESS;
address LINK = Constants.LINK_ADDRESS;
swapTradeFeeNumerator[USDC][USDCE] = 100;
swapTradeFeeNumerator[USDC][USDT] = 100;
swapTradeFeeNumerator[USDCE][USDC] = 100;
swapTradeFeeNumerator[USDCE][USDT] = 100;
swapTradeFeeNumerator[USDT][USDC] = 100;
swapTradeFeeNumerator[USDT][USDCE] = 100;
swapTradeFeeNumerator[WETH][ARB] = 500;
swapTradeFeeNumerator[WETH][WBTC] = 500;
swapTradeFeeNumerator[WETH][USDC] = 500;
swapTradeFeeNumerator[WETH][USDCE] = 500;
swapTradeFeeNumerator[WETH][USDT] = 500;
swapTradeFeeNumerator[ARB][WETH] = 500;
swapTradeFeeNumerator[WBTC][WETH] = 500;
swapTradeFeeNumerator[USDCE][ARB] = 500;
swapTradeFeeNumerator[USDCE][WETH] = 500;
swapTradeFeeNumerator[USDCE][WBTC] = 500;
swapTradeFeeNumerator[USDT][WETH] = 500;
swapTradeFeeNumerator[WETH][RDNT] = 3000;
swapTradeFeeNumerator[WETH][LINK] = 3000;
swapTradeFeeNumerator[RDNT][WETH] = 3000;
swapTradeFeeNumerator[LINK][WETH] = 3000;
}
function initializeSwapPath() internal {
address WETH = Constants.WETH_ADDRESS;
address ARB = Constants.ARB_ADDRESS;
address WBTC = Constants.WBTC_ADDRESS;
address USDC = Constants.USDC_ADDRESS;
address USDCE = Constants.USDCE_ADDRESS;
address USDT = Constants.USDT_ADDRESS;
address RDNT = Constants.RDNT_ADDRESS;
address LINK = Constants.LINK_ADDRESS;
swapPath[USDC][USDCE] = [USDC, USDCE];
swapPath[USDC][USDT] = [USDC, USDT];
swapPath[USDCE][USDC] = [USDCE, USDC];
swapPath[USDCE][USDT] = [USDCE, USDT];
swapPath[USDT][USDC] = [USDT, USDC];
swapPath[USDT][USDCE] = [USDT, USDCE];
swapPath[WETH][ARB] = [WETH, ARB];
swapPath[WETH][WBTC] = [WETH, WBTC];
swapPath[WETH][USDC] = [WETH, USDC];
swapPath[WETH][USDCE] = [WETH, USDCE];
swapPath[WETH][USDT] = [WETH, USDT];
swapPath[ARB][WETH] = [ARB, WETH];
swapPath[WBTC][WETH] = [WBTC, WETH];
swapPath[USDCE][ARB] = [USDCE, ARB];
swapPath[USDCE][WETH] = [USDCE, WETH];
swapPath[USDT][WETH] = [USDT, WETH];
swapPath[WETH][RDNT] = [WETH, RDNT];
swapPath[WETH][LINK] = [WETH, LINK];
swapPath[RDNT][WETH] = [RDNT, WETH];
swapPath[LINK][WETH] = [LINK, WETH];
swapPath[ARB][WBTC] = [ARB, WETH, WBTC];
swapPath[ARB][USDC] = [ARB, WETH, USDC];
swapPath[ARB][USDCE] = [ARB, WETH, USDCE];
swapPath[ARB][USDT] = [ARB, WETH, USDT];
swapPath[ARB][RDNT] = [ARB, WETH, RDNT];
swapPath[ARB][LINK] = [ARB, WETH, LINK];
swapPath[WBTC][ARB] = [WBTC, WETH, ARB];
swapPath[WBTC][USDC] = [WBTC, WETH, USDC];
swapPath[WBTC][USDCE] = [WBTC, WETH, USDCE];
swapPath[WBTC][USDT] = [WBTC, WETH, USDT];
swapPath[WBTC][RDNT] = [WBTC, WETH, RDNT];
swapPath[WBTC][LINK] = [WBTC, WETH, LINK];
swapPath[USDC][ARB] = [USDC, USDCE, ARB];
swapPath[USDC][WETH] = [USDC, USDCE, WETH];
swapPath[USDC][WBTC] = [USDC, USDCE, WBTC];
swapPath[USDC][RDNT] = [USDC, USDCE, WETH, RDNT];
swapPath[USDC][LINK] = [USDC, USDCE, WETH, LINK];
swapPath[USDCE][WBTC] = [USDCE, WETH, WBTC];
swapPath[USDCE][RDNT] = [USDCE, WETH, RDNT];
swapPath[USDCE][LINK] = [USDCE, WETH, LINK];
swapPath[USDT][ARB] = [USDT, USDCE, ARB];
swapPath[USDT][WBTC] = [USDT, USDCE, WBTC];
swapPath[USDT][RDNT] = [USDT, WETH, RDNT];
swapPath[USDT][LINK] = [USDT, WETH, LINK];
swapPath[RDNT][ARB] = [RDNT, WETH, ARB];
swapPath[RDNT][WBTC] = [RDNT, WETH, WBTC];
swapPath[RDNT][USDC] = [RDNT, WETH, USDC];
swapPath[RDNT][USDCE] = [RDNT, WETH, USDCE];
swapPath[RDNT][USDT] = [RDNT, WETH, USDT];
swapPath[RDNT][LINK] = [RDNT, WETH, LINK];
swapPath[LINK][ARB] = [LINK, WETH, ARB];
swapPath[LINK][WBTC] = [LINK, WETH, WBTC];
swapPath[LINK][USDC] = [LINK, WETH, USDC];
swapPath[LINK][USDCE] = [LINK, WETH, USDCE];
swapPath[LINK][USDT] = [LINK, WETH, USDT];
swapPath[LINK][RDNT] = [LINK, WETH, RDNT];
}
}
{
"compilationTarget": {
"contracts/Zap.sol": "Zap"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"uint24","name":"_slippageToleranceNumerator","type":"uint24"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"bool","name":"isETH","type":"bool"},{"indexed":false,"internalType":"address","name":"inputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"inputAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"swapPath","type":"address[]"},{"indexed":false,"internalType":"uint24[]","name":"swapTradeFee","type":"uint24[]"}],"name":"MultiSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"bool","name":"isETH","type":"bool"},{"indexed":false,"internalType":"address","name":"inputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"inputAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"swapPath","type":"address[]"},{"indexed":false,"internalType":"uint24[]","name":"swapTradeFee","type":"uint24[]"}],"name":"SingleSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"slippageTolerance","type":"uint24"}],"name":"UpdateSlippageTolerance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"inputToken","type":"address"},{"indexed":true,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"address[]","name":"newSwapPath","type":"address[]"}],"name":"UpdateSwapPath","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"inputToken","type":"address"},{"indexed":true,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint24","name":"swapTradeFee","type":"uint24"}],"name":"UpdateSwapTradeFee","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"}],"name":"getEstimateSwapOutAmount","outputs":[{"internalType":"uint256","name":"estimateSwapOutAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"}],"name":"getMinimumSwapOutAmount","outputs":[{"internalType":"uint256","name":"minimumSwapOutAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"}],"name":"getSwapInfo","outputs":[{"internalType":"bool","name":"isPathDefined","type":"bool"},{"internalType":"address[]","name":"swapPathArray","type":"address[]"},{"internalType":"uint24[]","name":"swapTradeFeeArray","type":"uint24[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"}],"name":"getTokenExchangeRate","outputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint256","name":"tokenPriceWith18Decimals","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"slippageTolerance","type":"uint24"}],"name":"setSlippageToleranceNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address[]","name":"newSwapPath","type":"address[]"}],"name":"setSwapPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint24","name":"swapTradeFee","type":"uint24"}],"name":"setSwapTradeFeeNumerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippageToleranceNumerator","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isETH","type":"bool"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"swapToken","outputs":[{"internalType":"uint256","name":"outputAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isETH","type":"bool"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"uint256","name":"minimumSwapOutAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"swapTokenWithMinimumOutput","outputs":[{"internalType":"uint256","name":"outputAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"transactionDeadlineDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]