编译器
0.8.18+commit.87f61d96
文件 1 的 19:Constants.sol
pragma solidity ^0.8.0;
library Constants {
address public constant UNISWAP_V3_FACTORY_ADDRESS = address(0x33128a8fC17869897dcE68Ed026d694621f6FDfD);
address public constant NONFUNGIBLE_POSITION_MANAGER_ADDRESS = address(0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1);
address public constant SWAP_ROUTER_ADDRESS = address(0x2626664c2603336E57B271c5C0b26F421741e481);
address public constant WETH_ADDRESS = address(0x4200000000000000000000000000000000000006);
address public constant USDC_ADDRESS = address(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913);
address public constant DEGEN_ADDRESS = address(0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed);
address public constant BRETT_ADDRESS = address(0x532f27101965dd16442E59d40670FaF5eBB142E4);
address public constant TOSHI_ADDRESS = address(0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4);
address public constant CIRCLE_ADDRESS = address(0x5baBfc2F240bc5De90Eb7e19D789412dB1dEc402);
address public constant ROOST_ADDRESS = address(0xE1aBD004250AC8D1F199421d647e01d094FAa180);
address public constant AERO_ADDRESS = address(0x940181a94A35A4569E4529A3CDfB74e38FD98631);
address public constant INT_ADDRESS = address(0x968D6A288d7B024D5012c0B25d67A889E4E3eC19);
address public constant HIGHER_ADDRESS = address(0x0578d8A44db98B23BF096A382e016e29a5Ce0ffe);
address public constant KEYCAT_ADDRESS = address(0x9a26F5433671751C3276a065f57e5a02D2817973);
address public constant BLACK_HOLE_ADDRESS = address(0x000000000000000000000000000000000000dEaD);
}
文件 2 的 19: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 的 19:EthereumZap.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 "./EthereumZapInitializer.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract EthereumZap is IZap, IZapEvent, Ownable, EthereumZapInitializer {
using SafeMath for uint256;
uint24 public override slippageToleranceNumerator;
address public WETH;
constructor(address _constants, uint24 _slippageToleranceNumerator) EthereumZapInitializer(_constants) {
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 (uint256 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 (uint256 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 (uint256 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 (uint256 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, inputAmount, minimumSwapOutAmount, 0
)
);
emit SingleSwap(
recipient, isETH, inputToken, inputAmount, outputToken, outputAmount, swapPathArray, swapTradeFeeArray
);
} else {
bytes memory path = abi.encodePacked(swapPathArray[0]);
for (uint256 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, inputAmount, minimumSwapOutAmount)
);
emit MultiSwap(
recipient, isETH, inputToken, inputAmount, outputToken, outputAmount, swapPathArray, swapTradeFeeArray
);
}
}
}
文件 4 的 19:EthereumZapInitializer.sol
pragma solidity ^0.8.0;
import "../../interfaces/IConstants.sol";
contract EthereumZapInitializer {
IConstants public Constants;
uint256 public transactionDeadlineDuration = 300;
mapping(address => mapping(address => address[])) internal swapPath;
mapping(address => mapping(address => uint24)) internal swapTradeFeeNumerator;
constructor(address _constants) {
Constants = IConstants(_constants);
}
function initializeSwapTradeFeeNumerator() internal {
address WETH = Constants.WETH_ADDRESS();
address ARB = Constants.ARB_ADDRESS();
address WBTC = Constants.WBTC_ADDRESS();
address USDC = Constants.USDC_ADDRESS();
address USDT = Constants.USDT_ADDRESS();
address RDNT = Constants.RDNT_ADDRESS();
address LINK = Constants.LINK_ADDRESS();
swapTradeFeeNumerator[USDC][USDT] = 100;
swapTradeFeeNumerator[USDT][USDC] = 100;
swapTradeFeeNumerator[WETH][ARB] = 500;
swapTradeFeeNumerator[WETH][WBTC] = 500;
swapTradeFeeNumerator[WETH][USDC] = 500;
swapTradeFeeNumerator[WETH][USDT] = 500;
swapTradeFeeNumerator[ARB][WETH] = 500;
swapTradeFeeNumerator[WBTC][WETH] = 500;
swapTradeFeeNumerator[USDC][ARB] = 500;
swapTradeFeeNumerator[USDC][WETH] = 500;
swapTradeFeeNumerator[USDC][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 USDT = Constants.USDT_ADDRESS();
address RDNT = Constants.RDNT_ADDRESS();
address LINK = Constants.LINK_ADDRESS();
swapPath[USDC][USDT] = [USDC, USDT];
swapPath[USDT][USDC] = [USDT, USDC];
swapPath[WETH][ARB] = [WETH, ARB];
swapPath[WETH][WBTC] = [WETH, WBTC];
swapPath[WETH][USDC] = [WETH, USDC];
swapPath[WETH][USDT] = [WETH, USDT];
swapPath[ARB][WETH] = [ARB, WETH];
swapPath[WBTC][WETH] = [WBTC, 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][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][USDT] = [WBTC, WETH, USDT];
swapPath[WBTC][RDNT] = [WBTC, WETH, RDNT];
swapPath[WBTC][LINK] = [WBTC, WETH, LINK];
swapPath[USDC][ARB] = [USDC, ARB];
swapPath[USDC][WETH] = [USDC, WETH];
swapPath[USDC][WBTC] = [USDC, WBTC];
swapPath[USDC][RDNT] = [USDC, WETH, RDNT];
swapPath[USDC][LINK] = [USDC, WETH, LINK];
swapPath[USDT][ARB] = [USDT, ARB];
swapPath[USDT][WBTC] = [USDT, 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][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][USDT] = [LINK, WETH, USDT];
swapPath[LINK][RDNT] = [LINK, WETH, RDNT];
}
}
文件 5 的 19:IConstants.sol
pragma solidity ^0.8.0;
interface IConstants {
function UNISWAP_V3_FACTORY_ADDRESS() external view returns (address);
function NONFUNGIBLE_POSITION_MANAGER_ADDRESS() external view returns (address);
function SWAP_ROUTER_ADDRESS() external view returns (address);
function DISTRIBUTE_REWARD_ADDRESS() external view returns (address);
function WETH_ADDRESS() external view returns (address);
function WBTC_ADDRESS() external view returns (address);
function ARB_ADDRESS() external view returns (address);
function USDC_ADDRESS() external view returns (address);
function USDCE_ADDRESS() external view returns (address);
function USDT_ADDRESS() external view returns (address);
function RDNT_ADDRESS() external view returns (address);
function LINK_ADDRESS() external view returns (address);
function DEGEN_ADDRESS() external view returns (address);
function BRETT_ADDRESS() external view returns (address);
function TOSHI_ADDRESS() external view returns (address);
function CIRCLE_ADDRESS() external view returns (address);
function ROOST_ADDRESS() external view returns (address);
function AERO_ADDRESS() external view returns (address);
function INT_ADDRESS() external view returns (address);
function HIGHER_ADDRESS() external view returns (address);
function KEYCAT_ADDRESS() external view returns (address);
function BLACK_HOLE_ADDRESS() external view returns (address);
}
文件 6 的 19: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);
}
文件 7 的 19: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);
}
文件 8 的 19:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface ISwapRouter {
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);
}
文件 9 的 19:IUniswapV3Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV3Factory {
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
}
文件 10 的 19: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);
}
文件 11 的 19:IWETH9.sol
pragma solidity ^0.8.0;
import "./IERC20Querier.sol";
interface IWETH9 is IERC20Querier {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 12 的 19: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);
}
文件 13 的 19: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
);
}
文件 14 的 19: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);
}
}
文件 15 的 19: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"
);
}
}
文件 16 的 19: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);
}
}
文件 17 的 19: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;
}
}
}
文件 18 的 19: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");
}
}
文件 19 的 19: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;
}
{
"compilationTarget": {
"contracts/zap/ethereum/EthereumZap.sol": "EthereumZap"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_constants","type":"address"},{"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":"Constants","outputs":[{"internalType":"contract IConstants","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"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"}]