More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,166 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Avax Swaps | 39565763 | 483 days ago | IN | 19 AVAX | 0.00979879 | ||||
Avax Swaps | 39077538 | 495 days ago | IN | 55 AVAX | 0.12479915 | ||||
Avax Swaps | 38751448 | 502 days ago | IN | 2.80166028 AVAX | 0.01162305 | ||||
Avax Swaps | 37357640 | 535 days ago | IN | 6.09266453 AVAX | 0.01225789 | ||||
Avax Swaps | 37357621 | 535 days ago | IN | 6.09266453 AVAX | 0.01225789 | ||||
Avax Swaps | 37357605 | 535 days ago | IN | 6.09167291 AVAX | 0.01223126 | ||||
Avax Swaps | 37156230 | 540 days ago | IN | 4.5 AVAX | 0.00537743 | ||||
Avax Swaps | 37155803 | 540 days ago | IN | 1.03484446 AVAX | 0.01225757 | ||||
Avax Swaps | 36909475 | 545 days ago | IN | 5.01140234 AVAX | 0.01648328 | ||||
Avax Swaps | 36807333 | 548 days ago | IN | 3.92433169 AVAX | 0.01219143 | ||||
Avax Swaps | 36493920 | 555 days ago | IN | 6.98104516 AVAX | 0.01226406 | ||||
Avax Swaps | 36417864 | 557 days ago | IN | 33.08272265 AVAX | 0.01228561 | ||||
Avax Swaps | 36417819 | 557 days ago | IN | 33.08272265 AVAX | 0.01298102 | ||||
Avax Swaps | 36417793 | 557 days ago | IN | 33.08272265 AVAX | 0.0120538 | ||||
Avax Swaps | 36417700 | 557 days ago | IN | 33.04657025 AVAX | 0.01249708 | ||||
Avax Swaps | 36417642 | 557 days ago | IN | 33.04453494 AVAX | 0.01374887 | ||||
Avax Swaps | 36417538 | 557 days ago | IN | 33.04453494 AVAX | 0.01226533 | ||||
Avax Swaps | 36346245 | 559 days ago | IN | 11.83893279 AVAX | 0.01223189 | ||||
Avax Swaps | 36285089 | 560 days ago | IN | 5 AVAX | 0.00564818 | ||||
Avax Swaps | 36285035 | 560 days ago | IN | 12 AVAX | 0.00600908 | ||||
Avax Swaps | 36284922 | 560 days ago | IN | 12.09222512 AVAX | 0.01380031 | ||||
Avax Swaps | 36256352 | 561 days ago | IN | 4.2 AVAX | 0.0058309 | ||||
Avax Swaps | 36178615 | 563 days ago | IN | 5 AVAX | 0.00555593 | ||||
Avax Swaps | 36100867 | 565 days ago | IN | 4.281254 AVAX | 0.0060094 | ||||
Avax Swaps | 36077177 | 565 days ago | IN | 1.12323988 AVAX | 0.01219111 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
42738380 | 408 days ago | 0.12242552 AVAX | ||||
42309780 | 418 days ago | 0.02789598 AVAX | ||||
42171009 | 421 days ago | 0.01006509 AVAX | ||||
41856281 | 429 days ago | 0.03262731 AVAX | ||||
41833854 | 430 days ago | 0.02644959 AVAX | ||||
41833835 | 430 days ago | 0.02644959 AVAX | ||||
41760630 | 431 days ago | 0.05090066 AVAX | ||||
41753743 | 431 days ago | 0.01038261 AVAX | ||||
41752654 | 431 days ago | 0.00949222 AVAX | ||||
41619054 | 435 days ago | 0.03519078 AVAX | ||||
41619018 | 435 days ago | 0.03519078 AVAX | ||||
41580406 | 435 days ago | 0.0112106 AVAX | ||||
41150711 | 446 days ago | 0.01022469 AVAX | ||||
41069859 | 447 days ago | 0.0111992 AVAX | ||||
41069838 | 447 days ago | 0.0111992 AVAX | ||||
41015832 | 449 days ago | 0.02651145 AVAX | ||||
41015830 | 449 days ago | 0.02651145 AVAX | ||||
41000352 | 449 days ago | 0.00964194 AVAX | ||||
40732949 | 456 days ago | 0.03515332 AVAX | ||||
40670365 | 457 days ago | 0.02803014 AVAX | ||||
40649331 | 458 days ago | 0.01062264 AVAX | ||||
40360227 | 464 days ago | 0.04924369 AVAX | ||||
40303398 | 466 days ago | 0.00958882 AVAX | ||||
40211374 | 468 days ago | 0.02488281 AVAX | ||||
40211296 | 468 days ago | 0.02488281 AVAX |
Loading...
Loading
Contract Name:
AvaxSwaps
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: ISC pragma solidity ^0.8.13; import "../../adapters/SushiAdapter.sol"; import {IAvaxSwaps} from "./interfaces/IAvaxSwaps.sol"; import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol"; import {IWETH9} from "../../interfaces/IWETH9.sol"; import {IJoeRouter02} from "traderjoe/interfaces/IJoeRouter02.sol"; import {ILBRouter} from "traderjoe/interfaces/ILBRouter.sol"; import "./StargateAvax.sol"; contract AvaxSwaps is IAvaxSwaps, SushiAdapter, StargateAvax { using SafeERC20 for IERC20; error MoreThanZero(); error WithdrawFailed(); event FeePaid(address _token, uint256 _fee); modifier lock() { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } IWETH9 internal immutable weth; IJoeRouter02 internal immutable joeRouter; ILBRouter internal immutable joeLBRouter; address public immutable feeCollector; uint8 private locked = 1; struct SrcTransferParams { address token; address receiver; uint256 amount; } struct UniswapV2Params { uint256 amountIn; uint256 amountOutMin; address[] path; uint256 deadline; } struct LiquidityBookParams { uint256 amountIn; uint256 amountOutWithSlippage; uint256[] pairBinSteps; address[] tokenPath; } struct Arrays { IERC20[] path; } // Constants uint8 internal constant BATCH_DEPOSIT = 1; uint8 internal constant WETH_DEPOSIT = 2; uint8 internal constant SUSHI_LEGACY = 5; uint8 internal constant TRADER_JOE = 11; uint8 internal constant TRADER_JOE_LB = 12; uint8 internal constant WETH_WITHDRAW = 13; uint8 internal constant SRC_TRANSFER = 14; uint8 internal constant STARGATE = 15; constructor( IWETH9 _weth, address _joeRouter, address _joeLBRouter, address _feeCollector, address _factory, bytes32 _pairCodeHash, IStargateRouter _stargateRouter ) SushiAdapter(_factory, _pairCodeHash) StargateAvax(_stargateRouter) { weth = _weth; joeRouter = IJoeRouter02(_joeRouter); joeLBRouter = ILBRouter(_joeLBRouter); feeCollector = _feeCollector; } function avaxSwaps(uint8[] calldata steps, bytes[] calldata data) external payable lock { if (steps.length != data.length) revert MismatchedLengths(); for (uint256 i; i < steps.length; i++) { uint8 step = steps[i]; if (step == BATCH_DEPOSIT) { (address[] memory tokens, uint256[] memory amounts) = abi.decode(data[i], (address[], uint256[])); for (uint256 j; j < tokens.length; j++) { if (amounts[j] <= 0) revert MoreThanZero(); IERC20(tokens[j]).safeTransferFrom(msg.sender, address(this), amounts[j]); } } else if (step == WETH_DEPOSIT) { uint256 _amount = abi.decode(data[i], (uint256)); if (_amount <= 0) revert MoreThanZero(); IWETH9(weth).deposit{value: _amount}(); } else if (step == SUSHI_LEGACY) { SushiParams[] memory params = abi.decode(data[i], (SushiParams[])); for (uint256 j; j < params.length; j++) { _swapExactTokensForTokens(params[j]); } } else if (step == WETH_WITHDRAW) { (address to, uint256 amount) = abi.decode(data[i], (address, uint256)); amount = amount != 0 ? amount : IERC20(weth).balanceOf(address(this)); weth.withdraw(amount); uint256 ethFee = calculateFee(amount); SafeTransferLib.safeTransferETH(to, (amount - ethFee)); SafeTransferLib.safeTransferETH(feeCollector, ethFee); } else if (step == SRC_TRANSFER) { SrcTransferParams[] memory params = abi.decode(data[i], (SrcTransferParams[])); for (uint256 k; k < params.length; k++) { _srcTransfer(params[k].token, params[k].amount, params[k].receiver); } } else if (step == TRADER_JOE_LB) { Arrays memory array; LiquidityBookParams[] memory params = abi.decode(data[i], (LiquidityBookParams[])); for (uint256 j = 0; j < params.length; j++) { params[j].amountIn = params[j].amountIn == 0 ? IERC20(params[j].tokenPath[0]).balanceOf(address(this)) : params[j].amountIn; if ( IERC20(params[j].tokenPath[0]).allowance(address(this), address(joeLBRouter)) < params[j].amountIn ) { IERC20(params[j].tokenPath[0]).safeIncreaseAllowance(address(joeLBRouter), type(uint256).max); } address[] memory tokens = params[j].tokenPath; array.path = convertor(tokens, tokens.length); joeLBRouter.swapExactTokensForTokens( params[j].amountIn, params[j].amountOutWithSlippage, params[j].pairBinSteps, array.path, address(this), block.timestamp ); } } else if (step == TRADER_JOE) { UniswapV2Params[] memory params = abi.decode(data[i], (UniswapV2Params[])); for (uint256 j; j < params.length; j++) { params[j].amountIn = params[j].amountIn == 0 ? IERC20(params[j].path[0]).balanceOf(address(this)) : params[j].amountIn; if (IERC20(params[j].path[0]).allowance(address(this), address(joeRouter)) < params[j].amountIn) { IERC20(params[j].path[0]).safeIncreaseAllowance(address(joeRouter), type(uint256).max); } IJoeRouter02(joeRouter).swapExactTokensForTokens( params[j].amountIn, params[j].amountOutMin, params[j].path, address(this), params[j].deadline ); } } else if (step == STARGATE) { (StargateParams memory params, uint8[] memory stepperions, bytes[] memory datass) = abi.decode(data[i], (StargateParams, uint8[], bytes[])); stargateSwap(params, stepperions, datass); } } } function convertor(address[] memory _addr, uint256 length) private pure returns (IERC20[] memory) { IERC20[] memory path = new IERC20[](length); for (uint256 j; j < length; j++) { path[j] = IERC20(_addr[j]); } return path; } function _srcTransfer(address _token, uint256 amount, address to) private { amount = amount != 0 ? amount : IERC20(_token).balanceOf(address(this)); uint256 fee = calculateFee(amount); amount -= fee; IERC20(_token).safeTransfer(feeCollector, fee); IERC20(_token).safeTransfer(to, amount); emit FeePaid(_token, fee); } function calculateFee(uint256 amount) internal pure returns (uint256 fee) { fee = amount - ((amount * 9995) / 1e4); } receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "./interfaces/ILBPair.sol"; /** LBRouter errors */ error LBRouter__SenderIsNotWAVAX(); error LBRouter__PairNotCreated(address tokenX, address tokenY, uint256 binStep); error LBRouter__WrongAmounts(uint256 amount, uint256 reserve); error LBRouter__SwapOverflows(uint256 id); error LBRouter__BrokenSwapSafetyCheck(); error LBRouter__NotFactoryOwner(); error LBRouter__TooMuchTokensIn(uint256 excess); error LBRouter__BinReserveOverflows(uint256 id); error LBRouter__IdOverflows(int256 id); error LBRouter__LengthsMismatch(); error LBRouter__WrongTokenOrder(); error LBRouter__IdSlippageCaught(uint256 activeIdDesired, uint256 idSlippage, uint256 activeId); error LBRouter__AmountSlippageCaught(uint256 amountXMin, uint256 amountX, uint256 amountYMin, uint256 amountY); error LBRouter__IdDesiredOverflows(uint256 idDesired, uint256 idSlippage); error LBRouter__FailedToSendAVAX(address recipient, uint256 amount); error LBRouter__DeadlineExceeded(uint256 deadline, uint256 currentTimestamp); error LBRouter__AmountSlippageBPTooBig(uint256 amountSlippage); error LBRouter__InsufficientAmountOut(uint256 amountOutMin, uint256 amountOut); error LBRouter__MaxAmountInExceeded(uint256 amountInMax, uint256 amountIn); error LBRouter__InvalidTokenPath(address wrongToken); error LBRouter__InvalidVersion(uint256 version); error LBRouter__WrongAvaxLiquidityParameters( address tokenX, address tokenY, uint256 amountX, uint256 amountY, uint256 msgValue ); /** LBToken errors */ error LBToken__SpenderNotApproved(address owner, address spender); error LBToken__TransferFromOrToAddress0(); error LBToken__MintToAddress0(); error LBToken__BurnFromAddress0(); error LBToken__BurnExceedsBalance(address from, uint256 id, uint256 amount); error LBToken__LengthMismatch(uint256 accountsLength, uint256 idsLength); error LBToken__SelfApproval(address owner); error LBToken__TransferExceedsBalance(address from, uint256 id, uint256 amount); error LBToken__TransferToSelf(); /** LBFactory errors */ error LBFactory__IdenticalAddresses(IERC20 token); error LBFactory__QuoteAssetNotWhitelisted(IERC20 quoteAsset); error LBFactory__QuoteAssetAlreadyWhitelisted(IERC20 quoteAsset); error LBFactory__AddressZero(); error LBFactory__LBPairAlreadyExists(IERC20 tokenX, IERC20 tokenY, uint256 _binStep); error LBFactory__LBPairNotCreated(IERC20 tokenX, IERC20 tokenY, uint256 binStep); error LBFactory__DecreasingPeriods(uint16 filterPeriod, uint16 decayPeriod); error LBFactory__ReductionFactorOverflows(uint16 reductionFactor, uint256 max); error LBFactory__VariableFeeControlOverflows(uint16 variableFeeControl, uint256 max); error LBFactory__BaseFeesBelowMin(uint256 baseFees, uint256 minBaseFees); error LBFactory__FeesAboveMax(uint256 fees, uint256 maxFees); error LBFactory__FlashLoanFeeAboveMax(uint256 fees, uint256 maxFees); error LBFactory__BinStepRequirementsBreached(uint256 lowerBound, uint16 binStep, uint256 higherBound); error LBFactory__ProtocolShareOverflows(uint16 protocolShare, uint256 max); error LBFactory__FunctionIsLockedForUsers(address user); error LBFactory__FactoryLockIsAlreadyInTheSameState(); error LBFactory__LBPairIgnoredIsAlreadyInTheSameState(); error LBFactory__BinStepHasNoPreset(uint256 binStep); error LBFactory__SameFeeRecipient(address feeRecipient); error LBFactory__SameFlashLoanFee(uint256 flashLoanFee); error LBFactory__LBPairSafetyCheckFailed(address LBPairImplementation); error LBFactory__SameImplementation(address LBPairImplementation); error LBFactory__ImplementationNotSet(); /** LBPair errors */ error LBPair__InsufficientAmounts(); error LBPair__AddressZero(); error LBPair__AddressZeroOrThis(); error LBPair__CompositionFactorFlawed(uint256 id); error LBPair__InsufficientLiquidityMinted(uint256 id); error LBPair__InsufficientLiquidityBurned(uint256 id); error LBPair__WrongLengths(); error LBPair__OnlyStrictlyIncreasingId(); error LBPair__OnlyFactory(); error LBPair__DistributionsOverflow(); error LBPair__OnlyFeeRecipient(address feeRecipient, address sender); error LBPair__OracleNotEnoughSample(); error LBPair__AlreadyInitialized(); error LBPair__OracleNewSizeTooSmall(uint256 newSize, uint256 oracleSize); error LBPair__FlashLoanCallbackFailed(); error LBPair__FlashLoanInvalidBalance(); error LBPair__FlashLoanInvalidToken(); /** BinHelper errors */ error BinHelper__BinStepOverflows(uint256 bp); error BinHelper__IdOverflows(); /** Math128x128 errors */ error Math128x128__PowerUnderflow(uint256 x, int256 y); error Math128x128__LogUnderflow(); /** Math512Bits errors */ error Math512Bits__MulDivOverflow(uint256 prod1, uint256 denominator); error Math512Bits__ShiftDivOverflow(uint256 prod1, uint256 denominator); error Math512Bits__MulShiftOverflow(uint256 prod1, uint256 offset); error Math512Bits__OffsetOverflows(uint256 offset); /** Oracle errors */ error Oracle__AlreadyInitialized(uint256 _index); error Oracle__LookUpTimestampTooOld(uint256 _minTimestamp, uint256 _lookUpTimestamp); error Oracle__NotInitialized(); /** PendingOwnable errors */ error PendingOwnable__NotOwner(); error PendingOwnable__NotPendingOwner(); error PendingOwnable__PendingOwnerAlreadySet(); error PendingOwnable__NoPendingOwner(); error PendingOwnable__AddressZero(); /** ReentrancyGuardUpgradeable errors */ error ReentrancyGuardUpgradeable__ReentrantCall(); error ReentrancyGuardUpgradeable__AlreadyInitialized(); /** SafeCast errors */ error SafeCast__Exceeds256Bits(uint256 x); error SafeCast__Exceeds248Bits(uint256 x); error SafeCast__Exceeds240Bits(uint256 x); error SafeCast__Exceeds232Bits(uint256 x); error SafeCast__Exceeds224Bits(uint256 x); error SafeCast__Exceeds216Bits(uint256 x); error SafeCast__Exceeds208Bits(uint256 x); error SafeCast__Exceeds200Bits(uint256 x); error SafeCast__Exceeds192Bits(uint256 x); error SafeCast__Exceeds184Bits(uint256 x); error SafeCast__Exceeds176Bits(uint256 x); error SafeCast__Exceeds168Bits(uint256 x); error SafeCast__Exceeds160Bits(uint256 x); error SafeCast__Exceeds152Bits(uint256 x); error SafeCast__Exceeds144Bits(uint256 x); error SafeCast__Exceeds136Bits(uint256 x); error SafeCast__Exceeds128Bits(uint256 x); error SafeCast__Exceeds120Bits(uint256 x); error SafeCast__Exceeds112Bits(uint256 x); error SafeCast__Exceeds104Bits(uint256 x); error SafeCast__Exceeds96Bits(uint256 x); error SafeCast__Exceeds88Bits(uint256 x); error SafeCast__Exceeds80Bits(uint256 x); error SafeCast__Exceeds72Bits(uint256 x); error SafeCast__Exceeds64Bits(uint256 x); error SafeCast__Exceeds56Bits(uint256 x); error SafeCast__Exceeds48Bits(uint256 x); error SafeCast__Exceeds40Bits(uint256 x); error SafeCast__Exceeds32Bits(uint256 x); error SafeCast__Exceeds24Bits(uint256 x); error SafeCast__Exceeds16Bits(uint256 x); error SafeCast__Exceeds8Bits(uint256 x); /** TreeMath errors */ error TreeMath__ErrorDepthSearch(); /** JoeLibrary errors */ error JoeLibrary__IdenticalAddresses(); error JoeLibrary__AddressZero(); error JoeLibrary__InsufficientAmount(); error JoeLibrary__InsufficientLiquidity(); /** TokenHelper errors */ error TokenHelper__NonContract(); error TokenHelper__CallFailed(); error TokenHelper__TransferFailed(); /** LBQuoter errors */ error LBQuoter_InvalidLength();
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.10; /// @title Joe V1 Factory Interface /// @notice Interface to interact with Joe V1 Factory interface IJoeFactory { event PairCreated(address indexed token0, address indexed token1, address pair, uint256); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function migrator() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; function setMigrator(address) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.10; /// @title Joe V1 Router01 Interface /// @notice Interface to interact with Joe V1 Router interface IJoeRouter01 { function factory() external pure returns (address); function WAVAX() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns ( uint256 amountA, uint256 amountB, uint256 liquidity ); function addLiquidityAVAX( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountAVAX, uint256 liquidity ); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityAVAX( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountAVAX); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityAVAXWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountAVAX); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactAVAXForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function swapTokensForExactAVAX( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForAVAX( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapAVAXForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) external pure returns (uint256 amountB); function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountOut); function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.10; import "./IJoeRouter01.sol"; /// @title Joe V1 Router Interface /// @notice Interface to interact with Joe V1 Router interface IJoeRouter02 is IJoeRouter01 { function removeLiquidityAVAXSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline ) external returns (uint256 amountAVAX); function removeLiquidityAVAXWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountAVAXMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountAVAX); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactAVAXForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForAVAXSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./ILBPair.sol"; import "./IPendingOwnable.sol"; /// @title Liquidity Book Factory Interface /// @author Trader Joe /// @notice Required interface of LBFactory contract interface ILBFactory is IPendingOwnable { /// @dev Structure to store the LBPair information, such as: /// - binStep: The bin step of the LBPair /// - LBPair: The address of the LBPair /// - createdByOwner: Whether the pair was created by the owner of the factory /// - ignoredForRouting: Whether the pair is ignored for routing or not. An ignored pair will not be explored during routes finding struct LBPairInformation { uint16 binStep; ILBPair LBPair; bool createdByOwner; bool ignoredForRouting; } event LBPairCreated( IERC20 indexed tokenX, IERC20 indexed tokenY, uint256 indexed binStep, ILBPair LBPair, uint256 pid ); event FeeRecipientSet(address oldRecipient, address newRecipient); event FlashLoanFeeSet(uint256 oldFlashLoanFee, uint256 newFlashLoanFee); event FeeParametersSet( address indexed sender, ILBPair indexed LBPair, uint256 binStep, uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxVolatilityAccumulated ); event FactoryLockedStatusUpdated(bool unlocked); event LBPairImplementationSet(address oldLBPairImplementation, address LBPairImplementation); event LBPairIgnoredStateChanged(ILBPair indexed LBPair, bool ignored); event PresetSet( uint256 indexed binStep, uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxVolatilityAccumulated, uint256 sampleLifetime ); event PresetRemoved(uint256 indexed binStep); event QuoteAssetAdded(IERC20 indexed quoteAsset); event QuoteAssetRemoved(IERC20 indexed quoteAsset); function MAX_FEE() external pure returns (uint256); function MIN_BIN_STEP() external pure returns (uint256); function MAX_BIN_STEP() external pure returns (uint256); function MAX_PROTOCOL_SHARE() external pure returns (uint256); function LBPairImplementation() external view returns (address); function getNumberOfQuoteAssets() external view returns (uint256); function getQuoteAsset(uint256 index) external view returns (IERC20); function isQuoteAsset(IERC20 token) external view returns (bool); function feeRecipient() external view returns (address); function flashLoanFee() external view returns (uint256); function creationUnlocked() external view returns (bool); function allLBPairs(uint256 id) external returns (ILBPair); function getNumberOfLBPairs() external view returns (uint256); function getLBPairInformation( IERC20 tokenX, IERC20 tokenY, uint256 binStep ) external view returns (LBPairInformation memory); function getPreset(uint16 binStep) external view returns ( uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxAccumulator, uint256 sampleLifetime ); function getAllBinSteps() external view returns (uint256[] memory presetsBinStep); function getAllLBPairs(IERC20 tokenX, IERC20 tokenY) external view returns (LBPairInformation[] memory LBPairsBinStep); function setLBPairImplementation(address LBPairImplementation) external; function createLBPair( IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep ) external returns (ILBPair pair); function setLBPairIgnored( IERC20 tokenX, IERC20 tokenY, uint256 binStep, bool ignored ) external; function setPreset( uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulated, uint16 sampleLifetime ) external; function removePreset(uint16 binStep) external; function setFeesParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulated ) external; function setFeeRecipient(address feeRecipient) external; function setFlashLoanFee(uint256 flashLoanFee) external; function setFactoryLockedState(bool locked) external; function addQuoteAsset(IERC20 quoteAsset) external; function removeQuoteAsset(IERC20 quoteAsset) external; function forceDecay(ILBPair LBPair) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title Liquidity Book Flashloan Callback Interface /// @author Trader Joe /// @notice Required interface to interact with LB flash loans interface ILBFlashLoanCallback { function LBFlashLoanCallback( address sender, IERC20 token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../libraries/FeeHelper.sol"; import "./ILBFactory.sol"; import "./ILBFlashLoanCallback.sol"; /// @title Liquidity Book Pair Interface /// @author Trader Joe /// @notice Required interface of LBPair contract interface ILBPair { /// @dev Structure to store the reserves of bins: /// - reserveX: The current reserve of tokenX of the bin /// - reserveY: The current reserve of tokenY of the bin struct Bin { uint112 reserveX; uint112 reserveY; uint256 accTokenXPerShare; uint256 accTokenYPerShare; } /// @dev Structure to store the information of the pair such as: /// slot0: /// - activeId: The current id used for swaps, this is also linked with the price /// - reserveX: The sum of amounts of tokenX across all bins /// slot1: /// - reserveY: The sum of amounts of tokenY across all bins /// - oracleSampleLifetime: The lifetime of an oracle sample /// - oracleSize: The current size of the oracle, can be increase by users /// - oracleActiveSize: The current active size of the oracle, composed only from non empty data sample /// - oracleLastTimestamp: The current last timestamp at which a sample was added to the circular buffer /// - oracleId: The current id of the oracle /// slot2: /// - feesX: The current amount of fees to distribute in tokenX (total, protocol) /// slot3: /// - feesY: The current amount of fees to distribute in tokenY (total, protocol) struct PairInformation { uint24 activeId; uint136 reserveX; uint136 reserveY; uint16 oracleSampleLifetime; uint16 oracleSize; uint16 oracleActiveSize; uint40 oracleLastTimestamp; uint16 oracleId; FeeHelper.FeesDistribution feesX; FeeHelper.FeesDistribution feesY; } /// @dev Structure to store the debts of users /// - debtX: The tokenX's debt /// - debtY: The tokenY's debt struct Debts { uint256 debtX; uint256 debtY; } /// @dev Structure to store fees: /// - tokenX: The amount of fees of token X /// - tokenY: The amount of fees of token Y struct Fees { uint128 tokenX; uint128 tokenY; } /// @dev Structure to minting informations: /// - amountXIn: The amount of token X sent /// - amountYIn: The amount of token Y sent /// - amountXAddedToPair: The amount of token X that have been actually added to the pair /// - amountYAddedToPair: The amount of token Y that have been actually added to the pair /// - activeFeeX: Fees X currently generated /// - activeFeeY: Fees Y currently generated /// - totalDistributionX: Total distribution of token X. Should be 1e18 (100%) or 0 (0%) /// - totalDistributionY: Total distribution of token Y. Should be 1e18 (100%) or 0 (0%) /// - id: Id of the current working bin when looping on the distribution array /// - amountX: The amount of token X deposited in the current bin /// - amountY: The amount of token Y deposited in the current bin /// - distributionX: Distribution of token X for the current working bin /// - distributionY: Distribution of token Y for the current working bin struct MintInfo { uint256 amountXIn; uint256 amountYIn; uint256 amountXAddedToPair; uint256 amountYAddedToPair; uint256 activeFeeX; uint256 activeFeeY; uint256 totalDistributionX; uint256 totalDistributionY; uint256 id; uint256 amountX; uint256 amountY; uint256 distributionX; uint256 distributionY; } event Swap( address indexed sender, address indexed recipient, uint256 indexed id, bool swapForY, uint256 amountIn, uint256 amountOut, uint256 volatilityAccumulated, uint256 fees ); event FlashLoan( address indexed sender, ILBFlashLoanCallback indexed receiver, IERC20 token, uint256 amount, uint256 fee ); event CompositionFee( address indexed sender, address indexed recipient, uint256 indexed id, uint256 feesX, uint256 feesY ); event DepositedToBin( address indexed sender, address indexed recipient, uint256 indexed id, uint256 amountX, uint256 amountY ); event WithdrawnFromBin( address indexed sender, address indexed recipient, uint256 indexed id, uint256 amountX, uint256 amountY ); event FeesCollected(address indexed sender, address indexed recipient, uint256 amountX, uint256 amountY); event ProtocolFeesCollected(address indexed sender, address indexed recipient, uint256 amountX, uint256 amountY); event OracleSizeIncreased(uint256 previousSize, uint256 newSize); function tokenX() external view returns (IERC20); function tokenY() external view returns (IERC20); function factory() external view returns (ILBFactory); function getReservesAndId() external view returns ( uint256 reserveX, uint256 reserveY, uint256 activeId ); function getGlobalFees() external view returns ( uint128 feesXTotal, uint128 feesYTotal, uint128 feesXProtocol, uint128 feesYProtocol ); function getOracleParameters() external view returns ( uint256 oracleSampleLifetime, uint256 oracleSize, uint256 oracleActiveSize, uint256 oracleLastTimestamp, uint256 oracleId, uint256 min, uint256 max ); function getOracleSampleFrom(uint256 timeDelta) external view returns ( uint256 cumulativeId, uint256 cumulativeAccumulator, uint256 cumulativeBinCrossed ); function feeParameters() external view returns (FeeHelper.FeeParameters memory); function findFirstNonEmptyBinId(uint24 id_, bool sentTokenY) external view returns (uint24 id); function getBin(uint24 id) external view returns (uint256 reserveX, uint256 reserveY); function pendingFees(address account, uint256[] memory ids) external view returns (uint256 amountX, uint256 amountY); function swap(bool sentTokenY, address to) external returns (uint256 amountXOut, uint256 amountYOut); function flashLoan( ILBFlashLoanCallback receiver, IERC20 token, uint256 amount, bytes calldata data ) external; function mint( uint256[] calldata ids, uint256[] calldata distributionX, uint256[] calldata distributionY, address to ) external returns ( uint256 amountXAddedToPair, uint256 amountYAddedToPair, uint256[] memory liquidityMinted ); function burn( uint256[] calldata ids, uint256[] calldata amounts, address to ) external returns (uint256 amountX, uint256 amountY); function increaseOracleLength(uint16 newSize) external; function collectFees(address account, uint256[] calldata ids) external returns (uint256 amountX, uint256 amountY); function collectProtocolFees() external returns (uint128 amountX, uint128 amountY); function setFeesParameters(bytes32 packedFeeParameters) external; function forceDecay() external; function initialize( IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 sampleLifetime, bytes32 packedFeeParameters ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "./IJoeFactory.sol"; import "./ILBPair.sol"; import "./ILBToken.sol"; import "./IWAVAX.sol"; /// @title Liquidity Book Router Interface /// @author Trader Joe /// @notice Required interface of LBRouter contract interface ILBRouter { /// @dev The liquidity parameters, such as: /// - tokenX: The address of token X /// - tokenY: The address of token Y /// - binStep: The bin step of the pair /// - amountX: The amount to send of token X /// - amountY: The amount to send of token Y /// - amountXMin: The min amount of token X added to liquidity /// - amountYMin: The min amount of token Y added to liquidity /// - activeIdDesired: The active id that user wants to add liquidity from /// - idSlippage: The number of id that are allowed to slip /// - deltaIds: The list of delta ids to add liquidity (`deltaId = activeId - desiredId`) /// - distributionX: The distribution of tokenX with sum(distributionX) = 100e18 (100%) or 0 (0%) /// - distributionY: The distribution of tokenY with sum(distributionY) = 100e18 (100%) or 0 (0%) /// - to: The address of the recipient /// - deadline: The deadline of the tx struct LiquidityParameters { IERC20 tokenX; IERC20 tokenY; uint256 binStep; uint256 amountX; uint256 amountY; uint256 amountXMin; uint256 amountYMin; uint256 activeIdDesired; uint256 idSlippage; int256[] deltaIds; uint256[] distributionX; uint256[] distributionY; address to; uint256 deadline; } function factory() external view returns (ILBFactory); function oldFactory() external view returns (IJoeFactory); function wavax() external view returns (IWAVAX); function getIdFromPrice(ILBPair LBPair, uint256 price) external view returns (uint24); function getPriceFromId(ILBPair LBPair, uint24 id) external view returns (uint256); function getSwapIn( ILBPair LBPair, uint256 amountOut, bool swapForY ) external view returns (uint256 amountIn, uint256 feesIn); function getSwapOut( ILBPair LBPair, uint256 amountIn, bool swapForY ) external view returns (uint256 amountOut, uint256 feesIn); function createLBPair( IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep ) external returns (ILBPair pair); function addLiquidity(LiquidityParameters calldata liquidityParameters) external returns (uint256[] memory depositIds, uint256[] memory liquidityMinted); function addLiquidityAVAX(LiquidityParameters calldata liquidityParameters) external payable returns (uint256[] memory depositIds, uint256[] memory liquidityMinted); function removeLiquidity( IERC20 tokenX, IERC20 tokenY, uint16 binStep, uint256 amountXMin, uint256 amountYMin, uint256[] memory ids, uint256[] memory amounts, address to, uint256 deadline ) external returns (uint256 amountX, uint256 amountY); function removeLiquidityAVAX( IERC20 token, uint16 binStep, uint256 amountTokenMin, uint256 amountAVAXMin, uint256[] memory ids, uint256[] memory amounts, address payable to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountAVAX); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external returns (uint256 amountOut); function swapExactTokensForAVAX( uint256 amountIn, uint256 amountOutMinAVAX, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address payable to, uint256 deadline ) external returns (uint256 amountOut); function swapExactAVAXForTokens( uint256 amountOutMin, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external payable returns (uint256 amountOut); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external returns (uint256[] memory amountsIn); function swapTokensForExactAVAX( uint256 amountOut, uint256 amountInMax, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address payable to, uint256 deadline ) external returns (uint256[] memory amountsIn); function swapAVAXForExactTokens( uint256 amountOut, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external payable returns (uint256[] memory amountsIn); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external returns (uint256 amountOut); function swapExactTokensForAVAXSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMinAVAX, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address payable to, uint256 deadline ) external returns (uint256 amountOut); function swapExactAVAXForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, uint256[] memory pairBinSteps, IERC20[] memory tokenPath, address to, uint256 deadline ) external payable returns (uint256 amountOut); function sweep( IERC20 token, address to, uint256 amount ) external; function sweepLBToken( ILBToken _lbToken, address _to, uint256[] calldata _ids, uint256[] calldata _amounts ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "openzeppelin/contracts/utils/introspection/IERC165.sol"; /// @title Liquidity Book Token Interface /// @author Trader Joe /// @notice Required interface of LBToken contract interface ILBToken is IERC165 { event TransferSingle(address indexed sender, address indexed from, address indexed to, uint256 id, uint256 amount); event TransferBatch( address indexed sender, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed account, address indexed sender, bool approved); function name() external view returns (string memory); function symbol() external view returns (string memory); function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory batchBalances); function totalSupply(uint256 id) external view returns (uint256); function isApprovedForAll(address owner, address spender) external view returns (bool); function setApprovalForAll(address sender, bool approved) external; function safeTransferFrom( address from, address to, uint256 id, uint256 amount ) external; function safeBatchTransferFrom( address from, address to, uint256[] calldata id, uint256[] calldata amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /// @title Liquidity Book Pending Ownable Interface /// @author Trader Joe /// @notice Required interface of Pending Ownable contract used for LBFactory interface IPendingOwnable { event PendingOwnerSet(address indexed pendingOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function owner() external view returns (address); function pendingOwner() external view returns (address); function setPendingOwner(address pendingOwner) external; function revokePendingOwner() external; function becomeOwner() external; function renounceOwnership() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title WAVAX Interface /// @notice Required interface of Wrapped AVAX contract interface IWAVAX is IERC20 { function deposit() external payable; function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /// @title Liquidity Book Constants Library /// @author Trader Joe /// @notice Set of constants for Liquidity Book contracts library Constants { uint256 internal constant SCALE_OFFSET = 128; uint256 internal constant SCALE = 1 << SCALE_OFFSET; uint256 internal constant PRECISION = 1e18; uint256 internal constant BASIS_POINT_MAX = 10_000; /// @dev The expected return after a successful flash loan bytes32 internal constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "./Constants.sol"; import "./SafeCast.sol"; import "./SafeMath.sol"; /// @title Liquidity Book Fee Helper Library /// @author Trader Joe /// @notice Helper contract used for fees calculation library FeeHelper { using SafeCast for uint256; using SafeMath for uint256; /// @dev Structure to store the protocol fees: /// - binStep: The bin step /// - baseFactor: The base factor /// - filterPeriod: The filter period, where the fees stays constant /// - decayPeriod: The decay period, where the fees are halved /// - reductionFactor: The reduction factor, used to calculate the reduction of the accumulator /// - variableFeeControl: The variable fee control, used to control the variable fee, can be 0 to disable them /// - protocolShare: The share of fees sent to protocol /// - maxVolatilityAccumulated: The max value of volatility accumulated /// - volatilityAccumulated: The value of volatility accumulated /// - volatilityReference: The value of volatility reference /// - indexRef: The index reference /// - time: The last time the accumulator was called struct FeeParameters { // 144 lowest bits in slot uint16 binStep; uint16 baseFactor; uint16 filterPeriod; uint16 decayPeriod; uint16 reductionFactor; uint24 variableFeeControl; uint16 protocolShare; uint24 maxVolatilityAccumulated; // 112 highest bits in slot uint24 volatilityAccumulated; uint24 volatilityReference; uint24 indexRef; uint40 time; } /// @dev Structure used during swaps to distributes the fees: /// - total: The total amount of fees /// - protocol: The amount of fees reserved for protocol struct FeesDistribution { uint128 total; uint128 protocol; } /// @notice Update the value of the volatility accumulated /// @param _fp The current fee parameters /// @param _activeId The current active id function updateVariableFeeParameters(FeeParameters memory _fp, uint256 _activeId) internal view { uint256 _deltaT = block.timestamp - _fp.time; if (_deltaT >= _fp.filterPeriod || _fp.time == 0) { _fp.indexRef = uint24(_activeId); if (_deltaT < _fp.decayPeriod) { unchecked { // This can't overflow as `reductionFactor <= BASIS_POINT_MAX` _fp.volatilityReference = uint24( (uint256(_fp.reductionFactor) * _fp.volatilityAccumulated) / Constants.BASIS_POINT_MAX ); } } else { _fp.volatilityReference = 0; } } _fp.time = (block.timestamp).safe40(); updateVolatilityAccumulated(_fp, _activeId); } /// @notice Update the volatility accumulated /// @param _fp The fee parameter /// @param _activeId The current active id function updateVolatilityAccumulated(FeeParameters memory _fp, uint256 _activeId) internal pure { uint256 volatilityAccumulated = (_activeId.absSub(_fp.indexRef) * Constants.BASIS_POINT_MAX) + _fp.volatilityReference; _fp.volatilityAccumulated = volatilityAccumulated > _fp.maxVolatilityAccumulated ? _fp.maxVolatilityAccumulated : uint24(volatilityAccumulated); } /// @notice Returns the base fee added to a swap, with 18 decimals /// @param _fp The current fee parameters /// @return The fee with 18 decimals precision function getBaseFee(FeeParameters memory _fp) internal pure returns (uint256) { unchecked { return uint256(_fp.baseFactor) * _fp.binStep * 1e10; } } /// @notice Returns the variable fee added to a swap, with 18 decimals /// @param _fp The current fee parameters /// @return variableFee The variable fee with 18 decimals precision function getVariableFee(FeeParameters memory _fp) internal pure returns (uint256 variableFee) { if (_fp.variableFeeControl != 0) { // Can't overflow as the max value is `max(uint24) * (max(uint24) * max(uint16)) ** 2 < max(uint104)` // It returns 18 decimals as: // decimals(variableFeeControl * (volatilityAccumulated * binStep)**2 / 100) = 4 + (4 + 4) * 2 - 2 = 18 unchecked { uint256 _prod = uint256(_fp.volatilityAccumulated) * _fp.binStep; variableFee = (_prod * _prod * _fp.variableFeeControl + 99) / 100; } } } /// @notice Return the amount of fees from an amount /// @dev Rounds amount up, follows `amount = amountWithFees - getFeeAmountFrom(fp, amountWithFees)` /// @param _fp The current fee parameter /// @param _amountWithFees The amount of token sent /// @return The fee amount from the amount sent function getFeeAmountFrom(FeeParameters memory _fp, uint256 _amountWithFees) internal pure returns (uint256) { return (_amountWithFees * getTotalFee(_fp) + Constants.PRECISION - 1) / (Constants.PRECISION); } /// @notice Return the fees to add to an amount /// @dev Rounds amount up, follows `amountWithFees = amount + getFeeAmount(fp, amount)` /// @param _fp The current fee parameter /// @param _amount The amount of token sent /// @return The fee amount to add to the amount function getFeeAmount(FeeParameters memory _fp, uint256 _amount) internal pure returns (uint256) { uint256 _fee = getTotalFee(_fp); uint256 _denominator = Constants.PRECISION - _fee; return (_amount * _fee + _denominator - 1) / _denominator; } /// @notice Return the fees added when an user adds liquidity and change the ratio in the active bin /// @dev Rounds amount up /// @param _fp The current fee parameter /// @param _amountWithFees The amount of token sent /// @return The fee amount function getFeeAmountForC(FeeParameters memory _fp, uint256 _amountWithFees) internal pure returns (uint256) { uint256 _fee = getTotalFee(_fp); uint256 _denominator = Constants.PRECISION * Constants.PRECISION; return (_amountWithFees * _fee * (_fee + Constants.PRECISION) + _denominator - 1) / _denominator; } /// @notice Return the fees distribution added to an amount /// @param _fp The current fee parameter /// @param _fees The fee amount /// @return fees The fee distribution function getFeeAmountDistribution(FeeParameters memory _fp, uint256 _fees) internal pure returns (FeesDistribution memory fees) { fees.total = _fees.safe128(); // unsafe math is fine because total >= protocol unchecked { fees.protocol = uint128((_fees * _fp.protocolShare) / Constants.BASIS_POINT_MAX); } } /// @notice Return the total fee, i.e. baseFee + variableFee /// @param _fp The current fee parameter /// @return The total fee, with 18 decimals function getTotalFee(FeeParameters memory _fp) private pure returns (uint256) { unchecked { return getBaseFee(_fp) + getVariableFee(_fp); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import "../LBErrors.sol"; /// @title Liquidity Book Safe Cast Library /// @author Trader Joe /// @notice Helper contract used for converting uint values safely library SafeCast { /// @notice Returns x on uint248 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint248 function safe248(uint256 x) internal pure returns (uint248 y) { if ((y = uint248(x)) != x) revert SafeCast__Exceeds248Bits(x); } /// @notice Returns x on uint240 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint240 function safe240(uint256 x) internal pure returns (uint240 y) { if ((y = uint240(x)) != x) revert SafeCast__Exceeds240Bits(x); } /// @notice Returns x on uint232 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint232 function safe232(uint256 x) internal pure returns (uint232 y) { if ((y = uint232(x)) != x) revert SafeCast__Exceeds232Bits(x); } /// @notice Returns x on uint224 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint224 function safe224(uint256 x) internal pure returns (uint224 y) { if ((y = uint224(x)) != x) revert SafeCast__Exceeds224Bits(x); } /// @notice Returns x on uint216 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint216 function safe216(uint256 x) internal pure returns (uint216 y) { if ((y = uint216(x)) != x) revert SafeCast__Exceeds216Bits(x); } /// @notice Returns x on uint208 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint208 function safe208(uint256 x) internal pure returns (uint208 y) { if ((y = uint208(x)) != x) revert SafeCast__Exceeds208Bits(x); } /// @notice Returns x on uint200 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint200 function safe200(uint256 x) internal pure returns (uint200 y) { if ((y = uint200(x)) != x) revert SafeCast__Exceeds200Bits(x); } /// @notice Returns x on uint192 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint192 function safe192(uint256 x) internal pure returns (uint192 y) { if ((y = uint192(x)) != x) revert SafeCast__Exceeds192Bits(x); } /// @notice Returns x on uint184 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint184 function safe184(uint256 x) internal pure returns (uint184 y) { if ((y = uint184(x)) != x) revert SafeCast__Exceeds184Bits(x); } /// @notice Returns x on uint176 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint176 function safe176(uint256 x) internal pure returns (uint176 y) { if ((y = uint176(x)) != x) revert SafeCast__Exceeds176Bits(x); } /// @notice Returns x on uint168 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint168 function safe168(uint256 x) internal pure returns (uint168 y) { if ((y = uint168(x)) != x) revert SafeCast__Exceeds168Bits(x); } /// @notice Returns x on uint160 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint160 function safe160(uint256 x) internal pure returns (uint160 y) { if ((y = uint160(x)) != x) revert SafeCast__Exceeds160Bits(x); } /// @notice Returns x on uint152 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint152 function safe152(uint256 x) internal pure returns (uint152 y) { if ((y = uint152(x)) != x) revert SafeCast__Exceeds152Bits(x); } /// @notice Returns x on uint144 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint144 function safe144(uint256 x) internal pure returns (uint144 y) { if ((y = uint144(x)) != x) revert SafeCast__Exceeds144Bits(x); } /// @notice Returns x on uint136 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint136 function safe136(uint256 x) internal pure returns (uint136 y) { if ((y = uint136(x)) != x) revert SafeCast__Exceeds136Bits(x); } /// @notice Returns x on uint128 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint128 function safe128(uint256 x) internal pure returns (uint128 y) { if ((y = uint128(x)) != x) revert SafeCast__Exceeds128Bits(x); } /// @notice Returns x on uint120 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint120 function safe120(uint256 x) internal pure returns (uint120 y) { if ((y = uint120(x)) != x) revert SafeCast__Exceeds120Bits(x); } /// @notice Returns x on uint112 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint112 function safe112(uint256 x) internal pure returns (uint112 y) { if ((y = uint112(x)) != x) revert SafeCast__Exceeds112Bits(x); } /// @notice Returns x on uint104 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint104 function safe104(uint256 x) internal pure returns (uint104 y) { if ((y = uint104(x)) != x) revert SafeCast__Exceeds104Bits(x); } /// @notice Returns x on uint96 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint96 function safe96(uint256 x) internal pure returns (uint96 y) { if ((y = uint96(x)) != x) revert SafeCast__Exceeds96Bits(x); } /// @notice Returns x on uint88 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint88 function safe88(uint256 x) internal pure returns (uint88 y) { if ((y = uint88(x)) != x) revert SafeCast__Exceeds88Bits(x); } /// @notice Returns x on uint80 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint80 function safe80(uint256 x) internal pure returns (uint80 y) { if ((y = uint80(x)) != x) revert SafeCast__Exceeds80Bits(x); } /// @notice Returns x on uint72 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint72 function safe72(uint256 x) internal pure returns (uint72 y) { if ((y = uint72(x)) != x) revert SafeCast__Exceeds72Bits(x); } /// @notice Returns x on uint64 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint64 function safe64(uint256 x) internal pure returns (uint64 y) { if ((y = uint64(x)) != x) revert SafeCast__Exceeds64Bits(x); } /// @notice Returns x on uint56 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint56 function safe56(uint256 x) internal pure returns (uint56 y) { if ((y = uint56(x)) != x) revert SafeCast__Exceeds56Bits(x); } /// @notice Returns x on uint48 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint48 function safe48(uint256 x) internal pure returns (uint48 y) { if ((y = uint48(x)) != x) revert SafeCast__Exceeds48Bits(x); } /// @notice Returns x on uint40 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint40 function safe40(uint256 x) internal pure returns (uint40 y) { if ((y = uint40(x)) != x) revert SafeCast__Exceeds40Bits(x); } /// @notice Returns x on uint32 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint32 function safe32(uint256 x) internal pure returns (uint32 y) { if ((y = uint32(x)) != x) revert SafeCast__Exceeds32Bits(x); } /// @notice Returns x on uint24 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint24 function safe24(uint256 x) internal pure returns (uint24 y) { if ((y = uint24(x)) != x) revert SafeCast__Exceeds24Bits(x); } /// @notice Returns x on uint16 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint16 function safe16(uint256 x) internal pure returns (uint16 y) { if ((y = uint16(x)) != x) revert SafeCast__Exceeds16Bits(x); } /// @notice Returns x on uint8 and check that it does not overflow /// @param x The value as an uint256 /// @return y The value as an uint8 function safe8(uint256 x) internal pure returns (uint8 y) { if ((y = uint8(x)) != x) revert SafeCast__Exceeds8Bits(x); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /// @title Liquidity Book Safe Math Helper Library /// @author Trader Joe /// @notice Helper contract used for calculating absolute value safely library SafeMath { /// @notice absSub, can't underflow or overflow /// @param x The first value /// @param y The second value /// @return The result of abs(x - y) function absSub(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return x > y ? x - y : y - x; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ 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)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 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 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } 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"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } 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"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ 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"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ 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"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ 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); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ 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); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ 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); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ 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 { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.12; // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library SafeMathUniswap { function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x, "ds-math-add-overflow"); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x, "ds-math-sub-underflow"); } function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0; import "sushiswap/protocols/sushiswap/contracts/interfaces/IUniswapV2Pair.sol"; import "./SafeMath.sol"; library UniswapV2Library { using SafeMathUniswap for uint256; // returns sorted token addresses, used to handle return values from pairs sorted in this order function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { require(tokenA != tokenB, "UniswapV2Library: IDENTICAL_ADDRESSES"); (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), "UniswapV2Library: ZERO_ADDRESS"); } // calculates the CREATE2 address for a pair without making any external calls function pairFor( address factory, address tokenA, address tokenB, bytes32 pairCodeHash ) internal pure returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factory, keccak256(abi.encodePacked(token0, token1)), pairCodeHash // init code hash ) ) ) ) ); } // fetches and sorts the reserves for a pair function getReserves( address factory, address tokenA, address tokenB, bytes32 pairCodeHash ) internal view returns (uint256 reserveA, uint256 reserveB) { (address token0, ) = sortTokens(tokenA, tokenB); (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair( pairFor(factory, tokenA, tokenB, pairCodeHash) ).getReserves(); (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); } // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) internal pure returns (uint256 amountB) { require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT"); require( reserveA > 0 && reserveB > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY" ); amountB = amountA.mul(reserveB) / reserveA; } // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) internal pure returns (uint256 amountOut) { require(amountIn > 0, "UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT"); require( reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY" ); uint256 amountInWithFee = amountIn.mul(997); uint256 numerator = amountInWithFee.mul(reserveOut); uint256 denominator = reserveIn.mul(1000).add(amountInWithFee); amountOut = numerator / denominator; } // given an output amount of an asset and pair reserves, returns a required input amount of the other asset function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) internal pure returns (uint256 amountIn) { require(amountOut > 0, "UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT"); require( reserveIn > 0 && reserveOut > 0, "UniswapV2Library: INSUFFICIENT_LIQUIDITY" ); uint256 numerator = reserveIn.mul(amountOut).mul(1000); uint256 denominator = reserveOut.sub(amountOut).mul(997); amountIn = (numerator / denominator).add(1); } // performs chained getAmountOut calculations on any number of pairs function getAmountsOut( address factory, uint256 amountIn, address[] memory path, bytes32 pairCodeHash ) internal view returns (uint256[] memory amounts) { require(path.length >= 2, "UniswapV2Library: INVALID_PATH"); amounts = new uint256[](path.length); amounts[0] = amountIn; for (uint256 i; i < path.length - 1; i++) { (uint256 reserveIn, uint256 reserveOut) = getReserves( factory, path[i], path[i + 1], pairCodeHash ); amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut); } } // performs chained getAmountIn calculations on any number of pairs function getAmountsIn( address factory, uint256 amountOut, address[] memory path, bytes32 pairCodeHash ) internal view returns (uint256[] memory amounts) { require(path.length >= 2, "UniswapV2Library: INVALID_PATH"); amounts = new uint256[](path.length); amounts[amounts.length - 1] = amountOut; for (uint256 i = path.length - 1; i > 0; i--) { (uint256 reserveIn, uint256 reserveOut) = getReserves( factory, path[i - 1], path[i], pairCodeHash ); amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); } } }
//SPDX-License-Identifier: ISC pragma solidity 0.8.17; import {IStargateReceiver} from "../../interfaces/IStargateReceiver.sol"; import {IStargateRouter} from "../../interfaces/IStargateRouter.sol"; import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IAvaxSwaps} from "./interfaces/IAvaxSwaps.sol"; import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol"; abstract contract StargateAvax is IStargateReceiver { using SafeERC20 for IERC20; /*////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////*/ ///@notice address of the stargate router IStargateRouter public immutable stargateRouter; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event ReceivedOnDestination(address indexed token, uint256 amountLD, bool failed, bool dustSent); error NotStgRouter(); error NotEnoughGas(); error MismatchedLengths(); /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(IStargateRouter _stargateRouter) { stargateRouter = _stargateRouter; } ///@notice struct to define parameters needed for the swap. struct StargateParams { uint16 dstChainId; // stargate dst chain id address token; // token getting bridged uint256 srcPoolId; // stargate src pool id uint256 dstPoolId; // stargate dst pool id uint256 amount; // amount to bridge uint256 amountMin; // amount to bridge minimum uint256 dustAmount; // native token to be received on dst chain address receiver; // Mugen contract on dst chain address to; // receiver bridge token incase of transaction reverts on dst chain uint256 gas; // extra gas to be sent for dst chain operations bytes32 srcContext; // random bytes32 as source context } /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @param params parameters for the stargate router defined in StargateParams /// @param stepsDst an array of steps to be performed on the dst chain /// @param dataDst an array of data to be performed on the dst chain function stargateSwap(StargateParams memory params, uint8[] memory stepsDst, bytes[] memory dataDst) internal { if (stepsDst.length != dataDst.length) revert MismatchedLengths(); if (params.gas < 100000) revert NotEnoughGas(); bytes memory payload = abi.encode(params.to, stepsDst, dataDst); params.amount = params.amount != 0 ? params.amount : IERC20(params.token).balanceOf(address(this)); if (IERC20(params.token).allowance(address(this), address(stargateRouter)) < params.amount) { IERC20(params.token).approve(address(stargateRouter), type(uint256).max); } IStargateRouter(stargateRouter).swap{value: address(this).balance}( params.dstChainId, params.srcPoolId, params.dstPoolId, payable(msg.sender), params.amount, params.amountMin, IStargateRouter.lzTxObj(params.gas, params.dustAmount, abi.encodePacked(params.receiver)), abi.encodePacked(params.receiver), payload ); } function getFee(StargateParams memory params, bytes memory payload) external view returns (uint256 _fee) { bytes memory toAddress = abi.encodePacked(params.receiver); (_fee,) = IStargateRouter(stargateRouter).quoteLayerZeroFee( params.dstChainId, 1, toAddress, payload, IStargateRouter.lzTxObj(params.gas, params.dustAmount, abi.encodePacked(params.receiver)) ); } /*////////////////////////////////////////////////////////////// STARGATE LOGIC //////////////////////////////////////////////////////////////*/ /// @param _token The token contract on the local chain /// @param amountLD The qty of local _token contract tokens /// @param _payload The bytes containing the toAddress function sgReceive(uint16, bytes memory, uint256, address _token, uint256 amountLD, bytes memory _payload) external override { if (msg.sender != address(stargateRouter)) revert NotStgRouter(); bool failed; bool dustSent; uint256 reserveGas = 100000; uint256 limit = gasleft() - reserveGas; (address to, uint8[] memory steps, bytes[] memory data) = abi.decode(_payload, (address, uint8[], bytes[])); if (gasleft() < reserveGas) { IERC20(_token).safeTransfer(to, amountLD); /// @dev transfer any native token received as dust to the to address if (address(this).balance > 0) { SafeTransferLib.safeTransferETH(to, address(this).balance); } } try IAvaxSwaps(payable(address(this))).avaxSwaps{gas: limit}(steps, data) {} catch (bytes memory) { IERC20(_token).safeTransfer(to, amountLD); failed = true; } if (address(this).balance > 0) { SafeTransferLib.safeTransferETH(to, address(this).balance); } emit ReceivedOnDestination(_token, amountLD, failed, dustSent); } }
//SPDX-License-Identifier: ISC pragma solidity ^0.8.13; interface IAvaxSwaps { function avaxSwaps(uint8[] calldata, bytes[] calldata) external payable; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.17; import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "sushiswap/protocols/sushixswap/contracts/libraries/UniswapV2Library.sol"; /// @title SushiLegacyAdapter /// @notice Adapter for functions used to swap using Sushiswap Legacy AMM. abstract contract SushiAdapter { using SafeERC20 for IERC20; /// @notice Sushiswap Legacy AMM Factory address public factory; /// @notice Sushiswap Legacy AMM PairCodeHash bytes32 public pairCodeHash; struct SushiParams { uint256 amountIn; uint256 amountOutMin; address[] path; bool sendTokens; } constructor(address _factory, bytes32 _pairCodeHash) { factory = _factory; pairCodeHash = _pairCodeHash; } function _swapExactTokensForTokens(SushiParams memory params) internal returns (uint256 amountOut) { params.amountIn = params.amountIn == 0 ? IERC20(params.path[0]).balanceOf(address(this)) : params.amountIn; uint256[] memory amounts = UniswapV2Library.getAmountsOut(factory, params.amountIn, params.path, pairCodeHash); amountOut = amounts[amounts.length - 1]; require(amountOut >= params.amountOutMin, "insufficient-amount-out"); /// @dev force sends token to the first pair if not already sent if (params.sendTokens) { IERC20(params.path[0]).safeTransfer( UniswapV2Library.pairFor(factory, params.path[0], params.path[1], pairCodeHash), params.amountIn ); } _swap(amounts, params.path, address(this)); } /// @dev requires the initial amount to have already been sent to the first pair function _swap(uint256[] memory amounts, address[] memory path, address _to) internal virtual { for (uint256 i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); (address token0,) = UniswapV2Library.sortTokens(input, output); uint256 amountOut = amounts[i + 1]; (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0)); address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2], pairCodeHash) : _to; IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output, pairCodeHash)).swap( amount0Out, amount1Out, to, new bytes(0) ); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.7.6; interface IStargateReceiver { function sgReceive( uint16 _srcChainId, // the remote chainId sending the tokens bytes memory _srcAddress, // the remote Bridge address uint256 _nonce, address _token, // the token contract on the local chain uint256 amountLD, // the qty of local _token contract tokens bytes memory payload ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; interface IStargateRouter { struct lzTxObj { uint256 dstGasForCall; uint256 dstNativeAmount; bytes dstNativeAddr; } function addLiquidity(uint256 _poolId, uint256 _amountLD, address _to) external; function swap( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLD, uint256 _minAmountLD, lzTxObj memory _lzTxParams, bytes calldata _to, bytes calldata _payload ) external payable; function redeemRemote( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, uint256 _minAmountLD, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function instantRedeemLocal(uint16 _srcPoolId, uint256 _amountLP, address _to) external returns (uint256); function redeemLocal( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function sendCredits(uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress) external payable; function quoteLayerZeroFee( uint16 _dstChainId, uint8 _functionType, bytes calldata _toAddress, bytes calldata _transferAndCallPayload, lzTxObj memory _lzTxParams ) external view returns (uint256, uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.13; import "openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title Interface for WETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
{ "remappings": [ "3xcaliSwap/=lib/3xcaliSwap/contracts/", "3xcaliswap/=lib/3xcaliswap/", "@core/=lib/3xcaliSwap/contracts/core/", "@openzeppelin/=lib/3xcaliSwap/node_modules/@openzeppelin/", "@solmate/=lib/3xcaliSwap/node_modules/solmate/src/", "LayerZero/=lib/contracts/lib/LayerZero/contracts/", "chainlink/=lib/chainlink/", "contracts/=lib/contracts/contracts/", "create3-factory/=lib/create3-factory/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "fraxlend/=lib/fraxlend/", "joe-v2/=lib/joe-v2/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/", "openzeppelin/=lib/openzeppelin-contracts/", "pancake-smart-contracts/=lib/pancake-smart-contracts/", "pancake/=lib/pancake-smart-contracts/", "solmate/=lib/solmate/", "spookyswap-core/=lib/spookyswap-core/contracts/", "spookyswap/=lib/spookyswap-core/", "sushiswap/=lib/sushiswap/", "traderjoe/=lib/joe-v2/src/", "uniswap/v3-core/=lib/v3-core/", "uniswap/v3-periphery/=lib/v3-periphery/", "utils/=lib/contracts/test/utils/", "v3-core/=lib/v3-core/", "v3-periphery/=lib/v3-periphery/contracts/", "velodrome/=lib/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IWETH9","name":"_weth","type":"address"},{"internalType":"address","name":"_joeRouter","type":"address"},{"internalType":"address","name":"_joeLBRouter","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"bytes32","name":"_pairCodeHash","type":"bytes32"},{"internalType":"contract IStargateRouter","name":"_stargateRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"MismatchedLengths","type":"error"},{"inputs":[],"name":"MoreThanZero","type":"error"},{"inputs":[],"name":"NotEnoughGas","type":"error"},{"inputs":[],"name":"NotStgRouter","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FeePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"},{"indexed":false,"internalType":"bool","name":"failed","type":"bool"},{"indexed":false,"internalType":"bool","name":"dustSent","type":"bool"}],"name":"ReceivedOnDestination","type":"event"},{"inputs":[{"internalType":"uint8[]","name":"steps","type":"uint8[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"avaxSwaps","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"srcPoolId","type":"uint256"},{"internalType":"uint256","name":"dstPoolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"uint256","name":"dustAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"bytes32","name":"srcContext","type":"bytes32"}],"internalType":"struct StargateAvax.StargateParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairCodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"sgReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stargateRouter","outputs":[{"internalType":"contract IStargateRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101206040526002805460ff191660011790553480156200001f57600080fd5b50604051620039683803806200396883398101604081905262000042916200009e565b600080546001600160a01b0319166001600160a01b03948516179055600191909155811660805293841660a05291831660c052821660e05216610100526200013d565b6001600160a01b03811681146200009b57600080fd5b50565b600080600080600080600060e0888a031215620000ba57600080fd5b8751620000c78162000085565b6020890151909750620000da8162000085565b6040890151909650620000ed8162000085565b6060890151909550620001008162000085565b6080890151909450620001138162000085565b60a089015160c08a015191945092506200012d8162000085565b8091505092959891949750929550565b60805160a05160c05160e0516101005161378c620001dc6000396000818161015c015281816108e801526115d4015260008181610bae01528181610c2d0152610cda015260008181610fac0152818161102b015261107f01526000818161066a015281816107cc015261085f01526000818160db015281816101c9015281816102ba015281816118de0152818161197401526119f6015261378c6000f3fe6080604052600436106100745760003560e01c8063ab8236f31161004e578063ab8236f314610115578063b2817fd514610137578063c415b95c1461014a578063c45a01551461017e57600080fd5b80634285f6e4146100805780639aab9248146100b3578063a9e56f3c146100c957600080fd5b3661007b57005b600080fd5b34801561008c57600080fd5b506100a061009b36600461271f565b61019e565b6040519081526020015b60405180910390f35b3480156100bf57600080fd5b506100a060015481565b3480156100d557600080fd5b506100fd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100aa565b34801561012157600080fd5b5061013561013036600461276f565b6102af565b005b61013561014536600461284d565b610467565b34801561015657600080fd5b506100fd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561018a57600080fd5b506000546100fd906001600160a01b031681565b6000808360e001516040516020016101b691906128b8565b60405160208183030381529060405290507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630a51236985600001516001848760405180606001604052808b610120015181526020018b60c0015181526020018b60e0015160405160200161023491906128b8565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610266959493929190612949565b6040805180830381865afa158015610282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a691906129a1565b50949350505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146102f857604051638afe477f60e01b815260040160405180910390fd5b600080620186a081815a61030c91906129db565b90506000806000878060200190518101906103279190612ae6565b925092509250845a1015610359576103496001600160a01b038b16848b61121d565b4715610359576103598347611285565b60405163b2817fd560e01b8152309063b2817fd59086906103809086908690600401612c4e565b600060405180830381600088803b15801561039a57600080fd5b5087f1935050505080156103ac575060015b6103fa573d8080156103da576040519150601f19603f3d011682016040523d82523d6000602084013e6103df565b606091505b506103f46001600160a01b038c16858c61121d565b60019750505b471561040a5761040a8347611285565b604080518a815288151560208201528715158183015290516001600160a01b038c16917f7f345d6da48bd1339fd428ff45265a0f01258b14ca09dcf8db0c469f4f732fd3919081900360600190a250505050505050505050505050565b60025460ff166001146104ae5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064015b60405180910390fd5b6002805460ff1916811790558281146104da576040516373f8993760e11b815260040160405180910390fd5b60005b838110156112095760008585838181106104f9576104f9612c7c565b905060200201602081019061050e9190612c92565b905060001960ff8216016106065760008085858581811061053157610531612c7c565b90506020028101906105439190612cb6565b8101906105509190612dbb565b9150915060005b82518110156105fe57600082828151811061057457610574612c7c565b60200260200101511161059a5760405163fe4155c760e01b815260040160405180910390fd5b6105ec33308484815181106105b1576105b1612c7c565b60200260200101518685815181106105cb576105cb612c7c565b60200260200101516001600160a01b03166112d6909392919063ffffffff16565b806105f681612e14565b915050610557565b5050506111f6565b60011960ff8216016106e257600084848481811061062657610626612c7c565b90506020028101906106389190612cb6565b8101906106459190612e2d565b9050600081116106685760405163fe4155c760e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b5050505050506111f6565b60041960ff82160161076b57600084848481811061070257610702612c7c565b90506020028101906107149190612cb6565b8101906107219190612e54565b905060005b81518110156107645761075182828151811061074457610744612c7c565b6020026020010151611314565b508061075c81612e14565b915050610726565b50506111f6565b600c1960ff82160161090d5760008085858581811061078c5761078c612c7c565b905060200281019061079e9190612cb6565b8101906107ab9190612f61565b9150915080600003610844576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561081b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083f9190612f8d565b610846565b805b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156108ab57600080fd5b505af11580156108bf573d6000803e3d6000fd5b5050505060006108ce82611508565b90506108e3836108de83856129db565b611285565b6105fe7f000000000000000000000000000000000000000000000000000000000000000082611285565b600d1960ff8216016109ce57600084848481811061092d5761092d612c7c565b905060200281019061093f9190612cb6565b81019061094c9190612fa6565b905060005b8151811015610764576109bc82828151811061096f5761096f612c7c565b60200260200101516000015183838151811061098d5761098d612c7c565b6020026020010151604001518484815181106109ab576109ab612c7c565b602002602001015160200151611533565b806109c681612e14565b915050610951565b600b1960ff821601610ddb5760408051602081019091526060815260008585858181106109fd576109fd612c7c565b9050602002810190610a0f9190612cb6565b810190610a1c9190613075565b905060005b81518110156105fe57818181518110610a3c57610a3c612c7c565b602002602001015160000151600014610a7257818181518110610a6157610a61612c7c565b602002602001015160000151610b16565b818181518110610a8457610a84612c7c565b602002602001015160600151600081518110610aa257610aa2612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190612f8d565b828281518110610b2857610b28612c7c565b60200260200101516000018181525050818181518110610b4a57610b4a612c7c565b602002602001015160000151828281518110610b6857610b68612c7c565b602002602001015160600151600081518110610b8657610b86612c7c565b6020908102919091010151604051636eb1769f60e11b81523060048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301529091169063dd62ed3e90604401602060405180830381865afa158015610bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c229190612f8d565b1015610c9f57610c9f7f0000000000000000000000000000000000000000000000000000000000000000600019848481518110610c6157610c61612c7c565b602002602001015160600151600081518110610c7f57610c7f612c7c565b60200260200101516001600160a01b03166116559092919063ffffffff16565b6000828281518110610cb357610cb3612c7c565b6020026020010151606001519050610ccc818251611707565b845282516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636d0ff49590859085908110610d1357610d13612c7c565b602002602001015160000151858581518110610d3157610d31612c7c565b602002602001015160200151868681518110610d4f57610d4f612c7c565b602002602001015160400151886000015130426040518763ffffffff1660e01b8152600401610d8396959493929190613187565b6020604051808303816000875af1158015610da2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc69190612f8d565b50508080610dd390612e14565b915050610a21565b600a1960ff82160161119f576000848484818110610dfb57610dfb612c7c565b9050602002810190610e0d9190612cb6565b810190610e1a9190613230565b905060005b815181101561076457818181518110610e3a57610e3a612c7c565b602002602001015160000151600014610e7057818181518110610e5f57610e5f612c7c565b602002602001015160000151610f14565b818181518110610e8257610e82612c7c565b602002602001015160400151600081518110610ea057610ea0612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f149190612f8d565b828281518110610f2657610f26612c7c565b60200260200101516000018181525050818181518110610f4857610f48612c7c565b602002602001015160000151828281518110610f6657610f66612c7c565b602002602001015160400151600081518110610f8457610f84612c7c565b6020908102919091010151604051636eb1769f60e11b81523060048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301529091169063dd62ed3e90604401602060405180830381865afa158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110209190612f8d565b101561107d5761107d7f000000000000000000000000000000000000000000000000000000000000000060001984848151811061105f5761105f612c7c565b602002602001015160400151600081518110610c7f57610c7f612c7c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166338ed17398383815181106110be576110be612c7c565b6020026020010151600001518484815181106110dc576110dc612c7c565b6020026020010151602001518585815181106110fa576110fa612c7c565b6020026020010151604001513087878151811061111957611119612c7c565b6020026020010151606001516040518663ffffffff1660e01b815260040161114595949392919061332a565b6000604051808303816000875af1158015611164573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261118c919081019061339b565b508061119781612e14565b915050610e1f565b600e1960ff8216016111f65760008060008686868181106111c2576111c2612c7c565b90506020028101906111d49190612cb6565b8101906111e1919061349f565b9250925092506111f28383836117b8565b5050505b508061120181612e14565b9150506104dd565b50506002805460ff19166001179055505050565b6040516001600160a01b03831660248201526044810182905261128090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611b06565b505050565b600080600080600085875af19050806112805760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b60448201526064016104a5565b6040516001600160a01b038085166024830152831660448201526064810182905261130e9085906323b872dd60e01b90608401611249565b50505050565b8051600090156113255781516113b0565b816040015160008151811061133c5761133c612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561138c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b09190612f8d565b80835260008054604085015160015492936113d9936001600160a01b0390931692909190611bd8565b905080600182516113ea91906129db565b815181106113fa576113fa612c7c565b6020026020010151915082602001518210156114585760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f757400000000000000000060448201526064016104a5565b8260600151156114f35760008054604085015180516114f3936114bb936001600160a01b0316929161148c5761148c612c7c565b602002602001015186604001516001815181106114ab576114ab612c7c565b6020026020010151600154611d5b565b8451604086015180516000906114d3576114d3612c7c565b60200260200101516001600160a01b031661121d9092919063ffffffff16565b61150281846040015130611e0f565b50919050565b60006127106115198361270b61356d565b6115239190613584565b61152d90836129db565b92915050565b816000036115a8576040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561157f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a39190612f8d565b6115aa565b815b915060006115b783611508565b90506115c381846129db565b92506115f96001600160a01b0385167f00000000000000000000000000000000000000000000000000000000000000008361121d565b61160d6001600160a01b038516838561121d565b604080516001600160a01b0386168152602081018390527f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f910160405180910390a150505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190612f8d565b6116d491906135a6565b6040516001600160a01b03851660248201526044810182905290915061130e90859063095ea7b360e01b90606401611249565b60606000826001600160401b0381111561172357611723612509565b60405190808252806020026020018201604052801561174c578160200160208202803683370190505b50905060005b838110156117b05784818151811061176c5761176c612c7c565b602002602001015182828151811061178657611786612c7c565b6001600160a01b0390921660209283029190910190910152806117a881612e14565b915050611752565b509392505050565b80518251146117da576040516373f8993760e11b815260040160405180910390fd5b620186a0836101200151101561180357604051636eb14fc360e11b815260040160405180910390fd5b6000836101000151838360405160200161181f939291906135b9565b604051602081830303815290604052905083608001516000036118af5760208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118aa9190612f8d565b6118b5565b83608001515b608085018190526020850151604051636eb1769f60e11b81523060048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301529091169063dd62ed3e90604401602060405180830381865afa15801561192e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119529190612f8d565b10156119f457602084015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f291906135f9565b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639fbf10fc47866000015187604001518860600151338a608001518b60a0015160405180606001604052808e610120015181526020018e60c0015181526020018e60e00151604051602001611a7391906128b8565b6040516020818303038152906040528152508d60e00151604051602001611a9a91906128b8565b6040516020818303038152906040528b6040518b63ffffffff1660e01b8152600401611ace99989796959493929190613616565b6000604051808303818588803b158015611ae757600080fd5b505af1158015611afb573d6000803e3d6000fd5b505050505050505050565b6000611b5b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fe69092919063ffffffff16565b8051909150156112805780806020019051810190611b7991906135f9565b6112805760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104a5565b6060600283511015611c2c5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f50415448000060448201526064016104a5565b82516001600160401b03811115611c4557611c45612509565b604051908082528060200260200182016040528015611c6e578160200160208202803683370190505b5090508381600081518110611c8557611c85612c7c565b60200260200101818152505060005b60018451611ca291906129db565b8110156102a657600080611cf688878581518110611cc257611cc2612c7c565b602002602001015188866001611cd891906135a6565b81518110611ce857611ce8612c7c565b602002602001015188611ffd565b91509150611d1e848481518110611d0f57611d0f612c7c565b602002602001015183836120c9565b84611d2a8560016135a6565b81518110611d3a57611d3a612c7c565b60200260200101818152505050508080611d5390612e14565b915050611c94565b6000806000611d6a86866121e8565b6040516001600160601b0319606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001611dec939291906001600160f81b0319815260609390931b6001600160601b03191660018401526015830191909152603582015260550190565b60408051601f198184030181529190528051602090910120979650505050505050565b60005b60018351611e2091906129db565b81101561130e57600080848381518110611e3c57611e3c612c7c565b602002602001015185846001611e5291906135a6565b81518110611e6257611e62612c7c565b6020026020010151915091506000611e7a83836121e8565b509050600087611e8b8660016135a6565b81518110611e9b57611e9b612c7c565b60200260200101519050600080836001600160a01b0316866001600160a01b031614611ec957826000611ecd565b6000835b91509150600060028a51611ee191906129db565b8810611eed5788611f1a565b600054611f1a906001600160a01b0316878c611f0a8c60026135a6565b815181106114ab576114ab612c7c565b9050611f3d60008054906101000a90046001600160a01b03168888600154611d5b565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015611f7a576020820181803683370190505b506040518563ffffffff1660e01b8152600401611f9a9493929190613693565b600060405180830381600087803b158015611fb457600080fd5b505af1158015611fc8573d6000803e3d6000fd5b50505050505050505050508080611fde90612e14565b915050611e12565b6060611ff584846000856122df565b949350505050565b600080600061200c86866121e8565b50905060008061201e89898989611d5b565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f91906136d7565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b0316146120b65780826120b9565b81815b909a909950975050505050505050565b600080841161212e5760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b60648201526084016104a5565b60008311801561213e5750600082115b61219b5760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b60648201526084016104a5565b60006121a9856103e56123af565b905060006121b782856123af565b905060006121d1836121cb886103e86123af565b90612416565b90506121dd8183613584565b979650505050505050565b600080826001600160a01b0316846001600160a01b03160361225a5760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b60648201526084016104a5565b826001600160a01b0316846001600160a01b03161061227a57828461227d565b83835b90925090506001600160a01b0382166122d85760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f41444452455353000060448201526064016104a5565b9250929050565b6060824710156123405760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104a5565b600080866001600160a01b0316858760405161235c9190613727565b60006040518083038185875af1925050503d8060008114612399576040519150601f19603f3d011682016040523d82523d6000602084013e61239e565b606091505b50915091506121dd8783838761246b565b60008115806123d3575082826123c5818361356d565b92506123d19083613584565b145b61152d5760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b60448201526064016104a5565b60008261242383826135a6565b915081101561152d5760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b60448201526064016104a5565b606083156124da5782516000036124d3576001600160a01b0385163b6124d35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104a5565b5081611ff5565b611ff583838151156124ef5781518083602001fd5b8060405162461bcd60e51b81526004016104a59190613743565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b038111828210171561254257612542612509565b60405290565b604051608081016001600160401b038111828210171561254257612542612509565b604051606081016001600160401b038111828210171561254257612542612509565b604051601f8201601f191681016001600160401b03811182821017156125b4576125b4612509565b604052919050565b803561ffff811681146125ce57600080fd5b919050565b6001600160a01b03811681146125e857600080fd5b50565b80356125ce816125d3565b6000610160828403121561260957600080fd5b61261161251f565b905061261c826125bc565b815261262a602083016125eb565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015261266d60e083016125eb565b60e08201526101006126808184016125eb565b9082015261012082810135908201526101409182013591810191909152919050565b60006001600160401b038211156126bb576126bb612509565b50601f01601f191660200190565b600082601f8301126126da57600080fd5b81356126ed6126e8826126a2565b61258c565b81815284602083860101111561270257600080fd5b816020850160208301376000918101602001919091529392505050565b600080610180838503121561273357600080fd5b61273d84846125f6565b91506101608301356001600160401b0381111561275957600080fd5b612765858286016126c9565b9150509250929050565b60008060008060008060c0878903121561278857600080fd5b612791876125bc565b955060208701356001600160401b03808211156127ad57600080fd5b6127b98a838b016126c9565b965060408901359550606089013591506127d2826125d3565b9093506080880135925060a088013590808211156127ef57600080fd5b506127fc89828a016126c9565b9150509295509295509295565b60008083601f84011261281b57600080fd5b5081356001600160401b0381111561283257600080fd5b6020830191508360208260051b85010111156122d857600080fd5b6000806000806040858703121561286357600080fd5b84356001600160401b038082111561287a57600080fd5b61288688838901612809565b9096509450602087013591508082111561289f57600080fd5b506128ac87828801612809565b95989497509550505050565b60609190911b6001600160601b031916815260140190565b60005b838110156128eb5781810151838201526020016128d3565b50506000910152565b6000815180845261290c8160208601602086016128d0565b601f01601f19169290920160200192915050565b80518252602081015160208301526000604082015160606040850152611ff560608501826128f4565b61ffff8616815260ff8516602082015260a06040820152600061296f60a08301866128f4565b828103606084015261298181866128f4565b905082810360808401526129958185612920565b98975050505050505050565b600080604083850312156129b457600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561152d5761152d6129c5565b60006001600160401b03821115612a0757612a07612509565b5060051b60200190565b60ff811681146125e857600080fd5b600082601f830112612a3157600080fd5b81516020612a416126e8836129ee565b82815260059290921b84018101918181019086841115612a6057600080fd5b8286015b84811015612adb5780516001600160401b03811115612a835760008081fd5b8701603f81018913612a955760008081fd5b848101516040612aa76126e8836126a2565b8281528b82848601011115612abc5760008081fd5b612acb838983018487016128d0565b8652505050918301918301612a64565b509695505050505050565b600080600060608486031215612afb57600080fd5b8351612b06816125d3565b809350506020808501516001600160401b0380821115612b2557600080fd5b818701915087601f830112612b3957600080fd5b8151612b476126e8826129ee565b81815260059190911b8301840190848101908a831115612b6657600080fd5b938501935b82851015612b8d578451612b7e81612a11565b82529385019390850190612b6b565b60408a01519097509450505080831115612ba657600080fd5b5050612bb486828701612a20565b9150509250925092565b600081518084526020808501945080840160005b83811015612bf157815160ff1687529582019590820190600101612bd2565b509495945050505050565b6000815180845260208085019450848260051b860182860160005b85811015612c41578383038952612c2f8383516128f4565b98850198925090840190600101612c17565b5090979650505050505050565b604081526000612c616040830185612bbe565b8281036020840152612c738185612bfc565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612ca457600080fd5b8135612caf81612a11565b9392505050565b6000808335601e19843603018112612ccd57600080fd5b8301803591506001600160401b03821115612ce757600080fd5b6020019150368190038213156122d857600080fd5b600082601f830112612d0d57600080fd5b81356020612d1d6126e8836129ee565b82815260059290921b84018101918181019086841115612d3c57600080fd5b8286015b84811015612adb578035612d53816125d3565b8352918301918301612d40565b600082601f830112612d7157600080fd5b81356020612d816126e8836129ee565b82815260059290921b84018101918181019086841115612da057600080fd5b8286015b84811015612adb5780358352918301918301612da4565b60008060408385031215612dce57600080fd5b82356001600160401b0380821115612de557600080fd5b612df186838701612cfc565b93506020850135915080821115612e0757600080fd5b5061276585828601612d60565b600060018201612e2657612e266129c5565b5060010190565b600060208284031215612e3f57600080fd5b5035919050565b80151581146125e857600080fd5b60006020808385031215612e6757600080fd5b82356001600160401b0380821115612e7e57600080fd5b818501915085601f830112612e9257600080fd5b8135612ea06126e8826129ee565b81815260059190911b83018401908481019088831115612ebf57600080fd5b8585015b83811015612f5457803585811115612eda57600080fd5b86016080818c03601f19011215612ef15760008081fd5b612ef9612548565b8882013581526040808301358a83015260608084013589811115612f1d5760008081fd5b612f2b8f8d83880101612cfc565b838501525060808401359350612f4084612e46565b820192909252845250918601918601612ec3565b5098975050505050505050565b60008060408385031215612f7457600080fd5b8235612f7f816125d3565b946020939093013593505050565b600060208284031215612f9f57600080fd5b5051919050565b60006020808385031215612fb957600080fd5b82356001600160401b03811115612fcf57600080fd5b8301601f81018513612fe057600080fd5b8035612fee6126e8826129ee565b8181526060918202830184019184820191908884111561300d57600080fd5b938501935b838510156130695780858a03121561302a5760008081fd5b61303261256a565b853561303d816125d3565b81528587013561304c816125d3565b818801526040868101359082015283529384019391850191613012565b50979650505050505050565b6000602080838503121561308857600080fd5b82356001600160401b038082111561309f57600080fd5b818501915085601f8301126130b357600080fd5b81356130c16126e8826129ee565b81815260059190911b830184019084810190888311156130e057600080fd5b8585015b83811015612f54578035858111156130fb57600080fd5b86016080818c03601f190112156131125760008081fd5b61311a612548565b8882013581526040808301358a8301526060808401358981111561313e5760008081fd5b61314c8f8d83880101612d60565b838501525060808401359150888211156131665760008081fd5b6131748e8c84870101612cfc565b90830152508452509186019186016130e4565b600060c082018883526020888185015260c0604085015281885180845260e086019150828a01935060005b818110156131ce578451835293830193918301916001016131b2565b50508481036060860152875180825290820192508188019060005b8181101561320e5782516001600160a01b0316855293830193918301916001016131e9565b505050506001600160a01b039490941660808301525060a00152949350505050565b6000602080838503121561324357600080fd5b82356001600160401b038082111561325a57600080fd5b818501915085601f83011261326e57600080fd5b813561327c6126e8826129ee565b81815260059190911b8301840190848101908883111561329b57600080fd5b8585015b83811015612f54578035858111156132b657600080fd5b86016080818c03601f190112156132cd5760008081fd5b6132d5612548565b8882013581526040808301358a830152606080840135898111156132f95760008081fd5b6133078f8d83880101612cfc565b92840192909252608093909301359282019290925284525091860191860161329f565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b8181101561337a5784516001600160a01b031683529383019391830191600101613355565b50506001600160a01b03969096166060850152505050608001529392505050565b600060208083850312156133ae57600080fd5b82516001600160401b038111156133c457600080fd5b8301601f810185136133d557600080fd5b80516133e36126e8826129ee565b81815260059190911b8201830190838101908783111561340257600080fd5b928401925b828410156121dd57835182529284019290840190613407565b600082601f83011261343157600080fd5b813560206134416126e8836129ee565b82815260059290921b8401810191818101908684111561346057600080fd5b8286015b84811015612adb5780356001600160401b038111156134835760008081fd5b6134918986838b01016126c9565b845250918301918301613464565b60008060006101a084860312156134b557600080fd5b6134bf85856125f6565b92506101608401356001600160401b03808211156134dc57600080fd5b818601915086601f8301126134f057600080fd5b813560206135006126e8836129ee565b82815260059290921b8401810191818101908a84111561351f57600080fd5b948201945b8386101561354657853561353781612a11565b82529482019490820190613524565b965050505061018086013591508082111561356057600080fd5b50612bb486828701613420565b808202811582820484141761152d5761152d6129c5565b6000826135a157634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561152d5761152d6129c5565b6001600160a01b03841681526060602082018190526000906135dd90830185612bbe565b82810360408401526135ef8185612bfc565b9695505050505050565b60006020828403121561360b57600080fd5b8151612caf81612e46565b600061012061ffff8c1683528a602084015289604084015260018060a01b03891660608401528760808401528660a08401528060c084015261365a81840187612920565b905082810360e084015261366e81866128f4565b905082810361010084015261368381856128f4565b9c9b505050505050505050505050565b84815283602082015260018060a01b03831660408201526080606082015260006135ef60808301846128f4565b80516001600160701b03811681146125ce57600080fd5b6000806000606084860312156136ec57600080fd5b6136f5846136c0565b9250613703602085016136c0565b9150604084015163ffffffff8116811461371c57600080fd5b809150509250925092565b600082516137398184602087016128d0565b9190910192915050565b602081526000612caf60208301846128f456fea2646970667358221220a25a09bbfa07257e810a5e855588d099d5bf2069b8154786325cc27a2857d1e964736f6c63430008110033000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c3000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac12000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c630300000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd
Deployed Bytecode
0x6080604052600436106100745760003560e01c8063ab8236f31161004e578063ab8236f314610115578063b2817fd514610137578063c415b95c1461014a578063c45a01551461017e57600080fd5b80634285f6e4146100805780639aab9248146100b3578063a9e56f3c146100c957600080fd5b3661007b57005b600080fd5b34801561008c57600080fd5b506100a061009b36600461271f565b61019e565b6040519081526020015b60405180910390f35b3480156100bf57600080fd5b506100a060015481565b3480156100d557600080fd5b506100fd7f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd81565b6040516001600160a01b0390911681526020016100aa565b34801561012157600080fd5b5061013561013036600461276f565b6102af565b005b61013561014536600461284d565b610467565b34801561015657600080fd5b506100fd7f000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac1281565b34801561018a57600080fd5b506000546100fd906001600160a01b031681565b6000808360e001516040516020016101b691906128b8565b60405160208183030381529060405290507f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd6001600160a01b0316630a51236985600001516001848760405180606001604052808b610120015181526020018b60c0015181526020018b60e0015160405160200161023491906128b8565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610266959493929190612949565b6040805180830381865afa158015610282573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a691906129a1565b50949350505050565b336001600160a01b037f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd16146102f857604051638afe477f60e01b815260040160405180910390fd5b600080620186a081815a61030c91906129db565b90506000806000878060200190518101906103279190612ae6565b925092509250845a1015610359576103496001600160a01b038b16848b61121d565b4715610359576103598347611285565b60405163b2817fd560e01b8152309063b2817fd59086906103809086908690600401612c4e565b600060405180830381600088803b15801561039a57600080fd5b5087f1935050505080156103ac575060015b6103fa573d8080156103da576040519150601f19603f3d011682016040523d82523d6000602084013e6103df565b606091505b506103f46001600160a01b038c16858c61121d565b60019750505b471561040a5761040a8347611285565b604080518a815288151560208201528715158183015290516001600160a01b038c16917f7f345d6da48bd1339fd428ff45265a0f01258b14ca09dcf8db0c469f4f732fd3919081900360600190a250505050505050505050505050565b60025460ff166001146104ae5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064015b60405180910390fd5b6002805460ff1916811790558281146104da576040516373f8993760e11b815260040160405180910390fd5b60005b838110156112095760008585838181106104f9576104f9612c7c565b905060200201602081019061050e9190612c92565b905060001960ff8216016106065760008085858581811061053157610531612c7c565b90506020028101906105439190612cb6565b8101906105509190612dbb565b9150915060005b82518110156105fe57600082828151811061057457610574612c7c565b60200260200101511161059a5760405163fe4155c760e01b815260040160405180910390fd5b6105ec33308484815181106105b1576105b1612c7c565b60200260200101518685815181106105cb576105cb612c7c565b60200260200101516001600160a01b03166112d6909392919063ffffffff16565b806105f681612e14565b915050610557565b5050506111f6565b60011960ff8216016106e257600084848481811061062657610626612c7c565b90506020028101906106389190612cb6565b8101906106459190612e2d565b9050600081116106685760405163fe4155c760e01b815260040160405180910390fd5b7f000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c76001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156106c357600080fd5b505af11580156106d7573d6000803e3d6000fd5b5050505050506111f6565b60041960ff82160161076b57600084848481811061070257610702612c7c565b90506020028101906107149190612cb6565b8101906107219190612e54565b905060005b81518110156107645761075182828151811061074457610744612c7c565b6020026020010151611314565b508061075c81612e14565b915050610726565b50506111f6565b600c1960ff82160161090d5760008085858581811061078c5761078c612c7c565b905060200281019061079e9190612cb6565b8101906107ab9190612f61565b9150915080600003610844576040516370a0823160e01b81523060048201527f000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c76001600160a01b0316906370a0823190602401602060405180830381865afa15801561081b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083f9190612f8d565b610846565b805b604051632e1a7d4d60e01b8152600481018290529091507f000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c76001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156108ab57600080fd5b505af11580156108bf573d6000803e3d6000fd5b5050505060006108ce82611508565b90506108e3836108de83856129db565b611285565b6105fe7f000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac1282611285565b600d1960ff8216016109ce57600084848481811061092d5761092d612c7c565b905060200281019061093f9190612cb6565b81019061094c9190612fa6565b905060005b8151811015610764576109bc82828151811061096f5761096f612c7c565b60200260200101516000015183838151811061098d5761098d612c7c565b6020026020010151604001518484815181106109ab576109ab612c7c565b602002602001015160200151611533565b806109c681612e14565b915050610951565b600b1960ff821601610ddb5760408051602081019091526060815260008585858181106109fd576109fd612c7c565b9050602002810190610a0f9190612cb6565b810190610a1c9190613075565b905060005b81518110156105fe57818181518110610a3c57610a3c612c7c565b602002602001015160000151600014610a7257818181518110610a6157610a61612c7c565b602002602001015160000151610b16565b818181518110610a8457610a84612c7c565b602002602001015160600151600081518110610aa257610aa2612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b169190612f8d565b828281518110610b2857610b28612c7c565b60200260200101516000018181525050818181518110610b4a57610b4a612c7c565b602002602001015160000151828281518110610b6857610b68612c7c565b602002602001015160600151600081518110610b8657610b86612c7c565b6020908102919091010151604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c3811660248301529091169063dd62ed3e90604401602060405180830381865afa158015610bfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c229190612f8d565b1015610c9f57610c9f7f000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c3600019848481518110610c6157610c61612c7c565b602002602001015160600151600081518110610c7f57610c7f612c7c565b60200260200101516001600160a01b03166116559092919063ffffffff16565b6000828281518110610cb357610cb3612c7c565b6020026020010151606001519050610ccc818251611707565b845282516001600160a01b037f000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c31690636d0ff49590859085908110610d1357610d13612c7c565b602002602001015160000151858581518110610d3157610d31612c7c565b602002602001015160200151868681518110610d4f57610d4f612c7c565b602002602001015160400151886000015130426040518763ffffffff1660e01b8152600401610d8396959493929190613187565b6020604051808303816000875af1158015610da2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc69190612f8d565b50508080610dd390612e14565b915050610a21565b600a1960ff82160161119f576000848484818110610dfb57610dfb612c7c565b9050602002810190610e0d9190612cb6565b810190610e1a9190613230565b905060005b815181101561076457818181518110610e3a57610e3a612c7c565b602002602001015160000151600014610e7057818181518110610e5f57610e5f612c7c565b602002602001015160000151610f14565b818181518110610e8257610e82612c7c565b602002602001015160400151600081518110610ea057610ea0612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f149190612f8d565b828281518110610f2657610f26612c7c565b60200260200101516000018181525050818181518110610f4857610f48612c7c565b602002602001015160000151828281518110610f6657610f66612c7c565b602002602001015160400151600081518110610f8457610f84612c7c565b6020908102919091010151604051636eb1769f60e11b81523060048201526001600160a01b037f00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4811660248301529091169063dd62ed3e90604401602060405180830381865afa158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110209190612f8d565b101561107d5761107d7f00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d460001984848151811061105f5761105f612c7c565b602002602001015160400151600081518110610c7f57610c7f612c7c565b7f00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d46001600160a01b03166338ed17398383815181106110be576110be612c7c565b6020026020010151600001518484815181106110dc576110dc612c7c565b6020026020010151602001518585815181106110fa576110fa612c7c565b6020026020010151604001513087878151811061111957611119612c7c565b6020026020010151606001516040518663ffffffff1660e01b815260040161114595949392919061332a565b6000604051808303816000875af1158015611164573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261118c919081019061339b565b508061119781612e14565b915050610e1f565b600e1960ff8216016111f65760008060008686868181106111c2576111c2612c7c565b90506020028101906111d49190612cb6565b8101906111e1919061349f565b9250925092506111f28383836117b8565b5050505b508061120181612e14565b9150506104dd565b50506002805460ff19166001179055505050565b6040516001600160a01b03831660248201526044810182905261128090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611b06565b505050565b600080600080600085875af19050806112805760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b60448201526064016104a5565b6040516001600160a01b038085166024830152831660448201526064810182905261130e9085906323b872dd60e01b90608401611249565b50505050565b8051600090156113255781516113b0565b816040015160008151811061133c5761133c612c7c565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561138c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b09190612f8d565b80835260008054604085015160015492936113d9936001600160a01b0390931692909190611bd8565b905080600182516113ea91906129db565b815181106113fa576113fa612c7c565b6020026020010151915082602001518210156114585760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f757400000000000000000060448201526064016104a5565b8260600151156114f35760008054604085015180516114f3936114bb936001600160a01b0316929161148c5761148c612c7c565b602002602001015186604001516001815181106114ab576114ab612c7c565b6020026020010151600154611d5b565b8451604086015180516000906114d3576114d3612c7c565b60200260200101516001600160a01b031661121d9092919063ffffffff16565b61150281846040015130611e0f565b50919050565b60006127106115198361270b61356d565b6115239190613584565b61152d90836129db565b92915050565b816000036115a8576040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561157f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a39190612f8d565b6115aa565b815b915060006115b783611508565b90506115c381846129db565b92506115f96001600160a01b0385167f000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac128361121d565b61160d6001600160a01b038516838561121d565b604080516001600160a01b0386168152602081018390527f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f910160405180910390a150505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190612f8d565b6116d491906135a6565b6040516001600160a01b03851660248201526044810182905290915061130e90859063095ea7b360e01b90606401611249565b60606000826001600160401b0381111561172357611723612509565b60405190808252806020026020018201604052801561174c578160200160208202803683370190505b50905060005b838110156117b05784818151811061176c5761176c612c7c565b602002602001015182828151811061178657611786612c7c565b6001600160a01b0390921660209283029190910190910152806117a881612e14565b915050611752565b509392505050565b80518251146117da576040516373f8993760e11b815260040160405180910390fd5b620186a0836101200151101561180357604051636eb14fc360e11b815260040160405180910390fd5b6000836101000151838360405160200161181f939291906135b9565b604051602081830303815290604052905083608001516000036118af5760208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118aa9190612f8d565b6118b5565b83608001515b608085018190526020850151604051636eb1769f60e11b81523060048201526001600160a01b037f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd811660248301529091169063dd62ed3e90604401602060405180830381865afa15801561192e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119529190612f8d565b10156119f457602084015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd8116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156119ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f291906135f9565b505b7f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd6001600160a01b0316639fbf10fc47866000015187604001518860600151338a608001518b60a0015160405180606001604052808e610120015181526020018e60c0015181526020018e60e00151604051602001611a7391906128b8565b6040516020818303038152906040528152508d60e00151604051602001611a9a91906128b8565b6040516020818303038152906040528b6040518b63ffffffff1660e01b8152600401611ace99989796959493929190613616565b6000604051808303818588803b158015611ae757600080fd5b505af1158015611afb573d6000803e3d6000fd5b505050505050505050565b6000611b5b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fe69092919063ffffffff16565b8051909150156112805780806020019051810190611b7991906135f9565b6112805760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104a5565b6060600283511015611c2c5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f50415448000060448201526064016104a5565b82516001600160401b03811115611c4557611c45612509565b604051908082528060200260200182016040528015611c6e578160200160208202803683370190505b5090508381600081518110611c8557611c85612c7c565b60200260200101818152505060005b60018451611ca291906129db565b8110156102a657600080611cf688878581518110611cc257611cc2612c7c565b602002602001015188866001611cd891906135a6565b81518110611ce857611ce8612c7c565b602002602001015188611ffd565b91509150611d1e848481518110611d0f57611d0f612c7c565b602002602001015183836120c9565b84611d2a8560016135a6565b81518110611d3a57611d3a612c7c565b60200260200101818152505050508080611d5390612e14565b915050611c94565b6000806000611d6a86866121e8565b6040516001600160601b0319606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001611dec939291906001600160f81b0319815260609390931b6001600160601b03191660018401526015830191909152603582015260550190565b60408051601f198184030181529190528051602090910120979650505050505050565b60005b60018351611e2091906129db565b81101561130e57600080848381518110611e3c57611e3c612c7c565b602002602001015185846001611e5291906135a6565b81518110611e6257611e62612c7c565b6020026020010151915091506000611e7a83836121e8565b509050600087611e8b8660016135a6565b81518110611e9b57611e9b612c7c565b60200260200101519050600080836001600160a01b0316866001600160a01b031614611ec957826000611ecd565b6000835b91509150600060028a51611ee191906129db565b8810611eed5788611f1a565b600054611f1a906001600160a01b0316878c611f0a8c60026135a6565b815181106114ab576114ab612c7c565b9050611f3d60008054906101000a90046001600160a01b03168888600154611d5b565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015611f7a576020820181803683370190505b506040518563ffffffff1660e01b8152600401611f9a9493929190613693565b600060405180830381600087803b158015611fb457600080fd5b505af1158015611fc8573d6000803e3d6000fd5b50505050505050505050508080611fde90612e14565b915050611e12565b6060611ff584846000856122df565b949350505050565b600080600061200c86866121e8565b50905060008061201e89898989611d5b565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f91906136d7565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b0316146120b65780826120b9565b81815b909a909950975050505050505050565b600080841161212e5760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b60648201526084016104a5565b60008311801561213e5750600082115b61219b5760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b60648201526084016104a5565b60006121a9856103e56123af565b905060006121b782856123af565b905060006121d1836121cb886103e86123af565b90612416565b90506121dd8183613584565b979650505050505050565b600080826001600160a01b0316846001600160a01b03160361225a5760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b60648201526084016104a5565b826001600160a01b0316846001600160a01b03161061227a57828461227d565b83835b90925090506001600160a01b0382166122d85760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f41444452455353000060448201526064016104a5565b9250929050565b6060824710156123405760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104a5565b600080866001600160a01b0316858760405161235c9190613727565b60006040518083038185875af1925050503d8060008114612399576040519150601f19603f3d011682016040523d82523d6000602084013e61239e565b606091505b50915091506121dd8783838761246b565b60008115806123d3575082826123c5818361356d565b92506123d19083613584565b145b61152d5760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b60448201526064016104a5565b60008261242383826135a6565b915081101561152d5760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b60448201526064016104a5565b606083156124da5782516000036124d3576001600160a01b0385163b6124d35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104a5565b5081611ff5565b611ff583838151156124ef5781518083602001fd5b8060405162461bcd60e51b81526004016104a59190613743565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b038111828210171561254257612542612509565b60405290565b604051608081016001600160401b038111828210171561254257612542612509565b604051606081016001600160401b038111828210171561254257612542612509565b604051601f8201601f191681016001600160401b03811182821017156125b4576125b4612509565b604052919050565b803561ffff811681146125ce57600080fd5b919050565b6001600160a01b03811681146125e857600080fd5b50565b80356125ce816125d3565b6000610160828403121561260957600080fd5b61261161251f565b905061261c826125bc565b815261262a602083016125eb565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015261266d60e083016125eb565b60e08201526101006126808184016125eb565b9082015261012082810135908201526101409182013591810191909152919050565b60006001600160401b038211156126bb576126bb612509565b50601f01601f191660200190565b600082601f8301126126da57600080fd5b81356126ed6126e8826126a2565b61258c565b81815284602083860101111561270257600080fd5b816020850160208301376000918101602001919091529392505050565b600080610180838503121561273357600080fd5b61273d84846125f6565b91506101608301356001600160401b0381111561275957600080fd5b612765858286016126c9565b9150509250929050565b60008060008060008060c0878903121561278857600080fd5b612791876125bc565b955060208701356001600160401b03808211156127ad57600080fd5b6127b98a838b016126c9565b965060408901359550606089013591506127d2826125d3565b9093506080880135925060a088013590808211156127ef57600080fd5b506127fc89828a016126c9565b9150509295509295509295565b60008083601f84011261281b57600080fd5b5081356001600160401b0381111561283257600080fd5b6020830191508360208260051b85010111156122d857600080fd5b6000806000806040858703121561286357600080fd5b84356001600160401b038082111561287a57600080fd5b61288688838901612809565b9096509450602087013591508082111561289f57600080fd5b506128ac87828801612809565b95989497509550505050565b60609190911b6001600160601b031916815260140190565b60005b838110156128eb5781810151838201526020016128d3565b50506000910152565b6000815180845261290c8160208601602086016128d0565b601f01601f19169290920160200192915050565b80518252602081015160208301526000604082015160606040850152611ff560608501826128f4565b61ffff8616815260ff8516602082015260a06040820152600061296f60a08301866128f4565b828103606084015261298181866128f4565b905082810360808401526129958185612920565b98975050505050505050565b600080604083850312156129b457600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561152d5761152d6129c5565b60006001600160401b03821115612a0757612a07612509565b5060051b60200190565b60ff811681146125e857600080fd5b600082601f830112612a3157600080fd5b81516020612a416126e8836129ee565b82815260059290921b84018101918181019086841115612a6057600080fd5b8286015b84811015612adb5780516001600160401b03811115612a835760008081fd5b8701603f81018913612a955760008081fd5b848101516040612aa76126e8836126a2565b8281528b82848601011115612abc5760008081fd5b612acb838983018487016128d0565b8652505050918301918301612a64565b509695505050505050565b600080600060608486031215612afb57600080fd5b8351612b06816125d3565b809350506020808501516001600160401b0380821115612b2557600080fd5b818701915087601f830112612b3957600080fd5b8151612b476126e8826129ee565b81815260059190911b8301840190848101908a831115612b6657600080fd5b938501935b82851015612b8d578451612b7e81612a11565b82529385019390850190612b6b565b60408a01519097509450505080831115612ba657600080fd5b5050612bb486828701612a20565b9150509250925092565b600081518084526020808501945080840160005b83811015612bf157815160ff1687529582019590820190600101612bd2565b509495945050505050565b6000815180845260208085019450848260051b860182860160005b85811015612c41578383038952612c2f8383516128f4565b98850198925090840190600101612c17565b5090979650505050505050565b604081526000612c616040830185612bbe565b8281036020840152612c738185612bfc565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612ca457600080fd5b8135612caf81612a11565b9392505050565b6000808335601e19843603018112612ccd57600080fd5b8301803591506001600160401b03821115612ce757600080fd5b6020019150368190038213156122d857600080fd5b600082601f830112612d0d57600080fd5b81356020612d1d6126e8836129ee565b82815260059290921b84018101918181019086841115612d3c57600080fd5b8286015b84811015612adb578035612d53816125d3565b8352918301918301612d40565b600082601f830112612d7157600080fd5b81356020612d816126e8836129ee565b82815260059290921b84018101918181019086841115612da057600080fd5b8286015b84811015612adb5780358352918301918301612da4565b60008060408385031215612dce57600080fd5b82356001600160401b0380821115612de557600080fd5b612df186838701612cfc565b93506020850135915080821115612e0757600080fd5b5061276585828601612d60565b600060018201612e2657612e266129c5565b5060010190565b600060208284031215612e3f57600080fd5b5035919050565b80151581146125e857600080fd5b60006020808385031215612e6757600080fd5b82356001600160401b0380821115612e7e57600080fd5b818501915085601f830112612e9257600080fd5b8135612ea06126e8826129ee565b81815260059190911b83018401908481019088831115612ebf57600080fd5b8585015b83811015612f5457803585811115612eda57600080fd5b86016080818c03601f19011215612ef15760008081fd5b612ef9612548565b8882013581526040808301358a83015260608084013589811115612f1d5760008081fd5b612f2b8f8d83880101612cfc565b838501525060808401359350612f4084612e46565b820192909252845250918601918601612ec3565b5098975050505050505050565b60008060408385031215612f7457600080fd5b8235612f7f816125d3565b946020939093013593505050565b600060208284031215612f9f57600080fd5b5051919050565b60006020808385031215612fb957600080fd5b82356001600160401b03811115612fcf57600080fd5b8301601f81018513612fe057600080fd5b8035612fee6126e8826129ee565b8181526060918202830184019184820191908884111561300d57600080fd5b938501935b838510156130695780858a03121561302a5760008081fd5b61303261256a565b853561303d816125d3565b81528587013561304c816125d3565b818801526040868101359082015283529384019391850191613012565b50979650505050505050565b6000602080838503121561308857600080fd5b82356001600160401b038082111561309f57600080fd5b818501915085601f8301126130b357600080fd5b81356130c16126e8826129ee565b81815260059190911b830184019084810190888311156130e057600080fd5b8585015b83811015612f54578035858111156130fb57600080fd5b86016080818c03601f190112156131125760008081fd5b61311a612548565b8882013581526040808301358a8301526060808401358981111561313e5760008081fd5b61314c8f8d83880101612d60565b838501525060808401359150888211156131665760008081fd5b6131748e8c84870101612cfc565b90830152508452509186019186016130e4565b600060c082018883526020888185015260c0604085015281885180845260e086019150828a01935060005b818110156131ce578451835293830193918301916001016131b2565b50508481036060860152875180825290820192508188019060005b8181101561320e5782516001600160a01b0316855293830193918301916001016131e9565b505050506001600160a01b039490941660808301525060a00152949350505050565b6000602080838503121561324357600080fd5b82356001600160401b038082111561325a57600080fd5b818501915085601f83011261326e57600080fd5b813561327c6126e8826129ee565b81815260059190911b8301840190848101908883111561329b57600080fd5b8585015b83811015612f54578035858111156132b657600080fd5b86016080818c03601f190112156132cd5760008081fd5b6132d5612548565b8882013581526040808301358a830152606080840135898111156132f95760008081fd5b6133078f8d83880101612cfc565b92840192909252608093909301359282019290925284525091860191860161329f565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b8181101561337a5784516001600160a01b031683529383019391830191600101613355565b50506001600160a01b03969096166060850152505050608001529392505050565b600060208083850312156133ae57600080fd5b82516001600160401b038111156133c457600080fd5b8301601f810185136133d557600080fd5b80516133e36126e8826129ee565b81815260059190911b8201830190838101908783111561340257600080fd5b928401925b828410156121dd57835182529284019290840190613407565b600082601f83011261343157600080fd5b813560206134416126e8836129ee565b82815260059290921b8401810191818101908684111561346057600080fd5b8286015b84811015612adb5780356001600160401b038111156134835760008081fd5b6134918986838b01016126c9565b845250918301918301613464565b60008060006101a084860312156134b557600080fd5b6134bf85856125f6565b92506101608401356001600160401b03808211156134dc57600080fd5b818601915086601f8301126134f057600080fd5b813560206135006126e8836129ee565b82815260059290921b8401810191818101908a84111561351f57600080fd5b948201945b8386101561354657853561353781612a11565b82529482019490820190613524565b965050505061018086013591508082111561356057600080fd5b50612bb486828701613420565b808202811582820484141761152d5761152d6129c5565b6000826135a157634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561152d5761152d6129c5565b6001600160a01b03841681526060602082018190526000906135dd90830185612bbe565b82810360408401526135ef8185612bfc565b9695505050505050565b60006020828403121561360b57600080fd5b8151612caf81612e46565b600061012061ffff8c1683528a602084015289604084015260018060a01b03891660608401528760808401528660a08401528060c084015261365a81840187612920565b905082810360e084015261366e81866128f4565b905082810361010084015261368381856128f4565b9c9b505050505050505050505050565b84815283602082015260018060a01b03831660408201526080606082015260006135ef60808301846128f4565b80516001600160701b03811681146125ce57600080fd5b6000806000606084860312156136ec57600080fd5b6136f5846136c0565b9250613703602085016136c0565b9150604084015163ffffffff8116811461371c57600080fd5b809150509250925092565b600082516137398184602087016128d0565b9190910192915050565b602081526000612caf60208301846128f456fea2646970667358221220a25a09bbfa07257e810a5e855588d099d5bf2069b8154786325cc27a2857d1e964736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c700000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c3000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac12000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c630300000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd
-----Decoded View---------------
Arg [0] : _weth (address): 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7
Arg [1] : _joeRouter (address): 0x60aE616a2155Ee3d9A68541Ba4544862310933d4
Arg [2] : _joeLBRouter (address): 0xE3Ffc583dC176575eEA7FD9dF2A7c65F7E23f4C3
Arg [3] : _feeCollector (address): 0xb5061624D13aa49Ef5345a2C65f7CcE173d5AC12
Arg [4] : _factory (address): 0xc35DADB65012eC5796536bD9864eD8773aBc74C4
Arg [5] : _pairCodeHash (bytes32): 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [6] : _stargateRouter (address): 0x45A01E4e04F14f7A4a6702c74187c5F6222033cd
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c7
Arg [1] : 00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4
Arg [2] : 000000000000000000000000e3ffc583dc176575eea7fd9df2a7c65f7e23f4c3
Arg [3] : 000000000000000000000000b5061624d13aa49ef5345a2c65f7cce173d5ac12
Arg [4] : 000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4
Arg [5] : e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [6] : 00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.