More Info
Private Name Tags
ContractCreator
Latest 5 from a total of 5 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Pending Admi... | 54878342 | 332 days ago | IN | 0 POL | 0.00226129 | ||||
Set Pending Emer... | 54878310 | 332 days ago | IN | 0 POL | 0.00226897 | ||||
Set Default Allo... | 47486719 | 521 days ago | IN | 0 POL | 0.08732195 | ||||
Set Exchange Res... | 47486708 | 521 days ago | IN | 0 POL | 0.00558031 | ||||
Set V Pool Manag... | 47486703 | 521 days ago | IN | 0 POL | 0.00559359 |
Latest 25 internal transactions (View All)
Loading...
Loading
Contract Name:
vPairFactory
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 833 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import './vPair.sol'; import './interfaces/IvPair.sol'; import './interfaces/IvPairFactory.sol'; import './interfaces/IvExchangeReserves.sol'; import './interfaces/IvSwapPoolDeployer.sol'; import './libraries/PoolAddress.sol'; import './types.sol'; import '@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol'; contract vPairFactory is IvPairFactory, IvSwapPoolDeployer { mapping(address => mapping(address => address)) public override pairs; address[] public override allPairs; address public override admin; address public override pendingAdmin; address public override emergencyAdmin; address public override pendingEmergencyAdmin; address public override exchangeReserves; address public override vPoolManager; address[] defaultAllowList; PoolCreationDefaults public override poolCreationDefaults; modifier onlyAdmin() { require(msg.sender == admin, 'OA'); _; } modifier onlyEmergencyAdmin() { require(msg.sender == emergencyAdmin, 'OEA'); _; } constructor() { admin = msg.sender; emergencyAdmin = msg.sender; } function createPair( address tokenA, address tokenB ) external override returns (address pair) { require(tokenA != tokenB, 'IA'); (address token0, address token1) = PoolAddress.orderAddresses( tokenA, tokenB ); require(token0 != address(0), 'ZA'); require(pairs[token0][token1] == address(0), 'PE'); poolCreationDefaults = PoolCreationDefaults({ factory: address(this), token0: token0, token1: token1, fee: 997, vFee: 997, maxReserveRatio: 2000 }); bytes32 _salt = PoolAddress.getSalt(token0, token1); pair = address(new vPair{salt: _salt}()); delete poolCreationDefaults; IvPair(pair).setAllowList(defaultAllowList); pairs[token0][token1] = pair; pairs[token1][token0] = pair; allPairs.push(pair); emit PairCreated(pair, address(this), token0, token1, 997, 997, 2000); return pair; } function setExchangeReservesAddress( address _exchangeReserves ) external override onlyAdmin { require(_exchangeReserves > address(0), 'IERA'); require( IvExchangeReserves(_exchangeReserves).factory() == address(this), 'IER' ); exchangeReserves = _exchangeReserves; emit ExchangeReserveAddressChanged(_exchangeReserves); } function setVPoolManagerAddress( address _vPoolManager ) external override onlyAdmin { require(_vPoolManager > address(0), 'IVPMA'); require( IvPoolManager(_vPoolManager).pairFactory() == address(this), 'IVPM' ); vPoolManager = _vPoolManager; emit FactoryVPoolManagerChanged(_vPoolManager); } function setPendingAdmin( address newPendingAdmin ) external override onlyAdmin { pendingAdmin = newPendingAdmin; emit FactoryNewPendingAdmin(newPendingAdmin); } function acceptAdmin() external override { require(msg.sender == pendingAdmin, 'OPA'); admin = pendingAdmin; pendingAdmin = address(0); emit FactoryNewAdmin(admin); } function setPendingEmergencyAdmin( address newPendingEmergencyAdmin ) external override onlyEmergencyAdmin { pendingEmergencyAdmin = newPendingEmergencyAdmin; emit FactoryNewPendingEmergencyAdmin(newPendingEmergencyAdmin); } function acceptEmergencyAdmin() external override { require(msg.sender == pendingEmergencyAdmin, 'OPA'); emergencyAdmin = pendingEmergencyAdmin; pendingEmergencyAdmin = address(0); emit FactoryNewEmergencyAdmin(emergencyAdmin); } function setDefaultAllowList( address[] calldata _defaultAllowList ) external override onlyAdmin { require(_defaultAllowList.length <= 2 ** 24 - 1, 'ATL'); for (uint i = 1; i < _defaultAllowList.length; ++i) { require(_defaultAllowList[i] > _defaultAllowList[i - 1], 'ALU'); } defaultAllowList = _defaultAllowList; emit DefaultAllowListChanged(_defaultAllowList); } function allPairsLength() external view override returns (uint256) { return allPairs.length; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import '@openzeppelin/contracts/utils/math/Math.sol'; import './interfaces/IvPair.sol'; import './interfaces/IvSwapPoolDeployer.sol'; import './interfaces/IvPairFactory.sol'; import './interfaces/IvPoolManager.sol'; import './interfaces/IvFlashSwapCallback.sol'; import './libraries/vSwapLibrary.sol'; import './vSwapERC20.sol'; contract vPair is IvPair, vSwapERC20, ReentrancyGuard { uint24 internal constant BASE_FACTOR = 1000; uint24 internal constant MINIMUM_LIQUIDITY = BASE_FACTOR; uint24 internal constant RESERVE_RATIO_FACTOR = BASE_FACTOR * 100; address public immutable factory; address public immutable override token0; address public immutable override token1; uint112 public override pairBalance0; uint112 public override pairBalance1; uint16 public override fee; uint16 public override vFee; uint128 public override lastSwapBlock; uint128 public override blocksDelay; uint256 public override reservesBaseValueSum; uint256 public override maxReserveRatio; uint256 public reserveRatioWarningThreshold; address[] public allowList; mapping(address => bool) public override allowListMap; bool public closed; mapping(address => uint256) public override reservesBaseValue; mapping(address => uint256) public override reserves; function _onlyFactoryAdmin() internal view { require( msg.sender == IvPairFactory(factory).admin() || msg.sender == factory, 'OA' ); } modifier onlyFactoryAdmin() { _onlyFactoryAdmin(); _; } modifier onlyEmergencyAdmin() { require(msg.sender == IvPairFactory(factory).emergencyAdmin(), 'OE'); _; } modifier isOpen() { require(!closed, 'C'); _; } /// @dev This function is gas optimized to avoid a redundant extcodesize check in addition to the returndatasize function fetchBalance(address token) internal view returns (uint256) { (bool success, bytes memory data) = token.staticcall( abi.encodeWithSignature('balanceOf(address)', address(this)) ); require(success && data.length >= 32, 'FBF'); return abi.decode(data, (uint256)); } constructor() { ( factory, token0, token1, fee, vFee, maxReserveRatio ) = IvSwapPoolDeployer(msg.sender).poolCreationDefaults(); reserveRatioWarningThreshold = 1900; blocksDelay = 40; } function _update(uint112 balance0, uint112 balance1) internal { lastSwapBlock = uint128(block.number); (pairBalance0, pairBalance1) = (balance0, balance1); emit vSync(balance0, balance1); } function getBalances() external view override returns (uint112 _balance0, uint112 _balance1) { return (pairBalance0, pairBalance1); } function getTokens() external view override returns (address _token0, address _token1) { return (token0, token1); } function swapNative( uint256 amountOut, address tokenOut, address to, bytes calldata data ) external override nonReentrant isOpen returns (uint256 _amountIn) { require(to > address(0) && to != token0 && to != token1, 'IT'); require(tokenOut == token0 || tokenOut == token1, 'NNT'); require(amountOut > 0, 'IAO'); address _tokenIn = tokenOut == token0 ? token1 : token0; (uint256 _balanceIn, uint256 _balanceOut) = vSwapLibrary.sortBalances( _tokenIn, token0, pairBalance0, pairBalance1 ); require(amountOut < _balanceOut, 'AOE'); SafeERC20.safeTransfer(IERC20(tokenOut), to, amountOut); uint256 requiredAmountIn = vSwapLibrary.getAmountIn( amountOut, _balanceIn, _balanceOut, fee ); if (data.length > 0) { IvFlashSwapCallback(msg.sender).vFlashSwapCallback( _tokenIn, tokenOut, requiredAmountIn, data ); } _amountIn = fetchBalance(_tokenIn) - _balanceIn; require(_amountIn > 0 && _amountIn >= requiredAmountIn, 'IIA'); { //avoid stack too deep bool _isTokenIn0 = _tokenIn == token0; _update( uint112( _isTokenIn0 ? _balanceIn + _amountIn : _balanceOut - amountOut ), uint112( _isTokenIn0 ? _balanceOut - amountOut : _balanceIn + _amountIn ) ); } emit Swap( msg.sender, _tokenIn, tokenOut, requiredAmountIn, amountOut, to ); } function swapNativeToReserve( uint256 amountOut, address ikPair, address to, uint256 incentivesLimitPct, bytes calldata data ) external override nonReentrant isOpen returns (address _leftoverToken, uint256 _leftoverAmount) { require(msg.sender == IvPairFactory(factory).exchangeReserves(), 'OA'); require(to > address(0) && to != token0 && to != token1, 'IT'); VirtualPoolModel memory vPool = IvPoolManager( IvPairFactory(factory).vPoolManager() ).getVirtualPool(ikPair, address(this)); // validate ikPair with factory require( IvPairFactory(factory).pairs(vPool.token1, vPool.commonToken) == ikPair, 'IIKP' ); require( amountOut <= vPool.balance1 && amountOut <= reserves[vPool.token1], 'AOE' ); require(allowListMap[vPool.token1], 'TNW'); require(vPool.token0 == token0 || vPool.token0 == token1, 'NNT'); SafeERC20.safeTransfer(IERC20(vPool.token1), to, amountOut); uint256 requiredAmountIn = vSwapLibrary.quote( amountOut, vPool.balance1, vPool.balance0 ); if (data.length > 0) IvFlashSwapCallback(msg.sender).vFlashSwapCallback( vPool.token0, vPool.token1, requiredAmountIn, data ); { // scope to avoid stack too deep errors uint256 balanceDiff = fetchBalance(vPool.token0) - (vPool.token0 == token0 ? pairBalance0 : pairBalance1); require(balanceDiff >= requiredAmountIn, 'IBD'); (_leftoverAmount, _leftoverToken) = ( Math.min( balanceDiff - requiredAmountIn, (balanceDiff * incentivesLimitPct) / 100 ), vPool.token0 ); if (_leftoverAmount > 0) { SafeERC20.safeTransfer( IERC20(_leftoverToken), msg.sender, _leftoverAmount ); } IvPoolManager(IvPairFactory(factory).vPoolManager()) .updateVirtualPoolBalances( ikPair, address(this), vPool.balance0 + balanceDiff - _leftoverAmount, vPool.balance1 - amountOut ); } { // scope to avoid stack too deep errors // //update reserve balance in the equivalent of token0 value uint256 reserveTokenBalance = fetchBalance(vPool.token1); // //re-calculate price of reserve asset in token0 for the whole pool balance uint256 _reserveBaseValue = reserveTokenBalance > 0 ? vSwapLibrary.quote( reserveTokenBalance, vPool.balance1, vPool.balance0 ) : 0; if (_reserveBaseValue > 0 && vPool.token0 == token1) { //if tokenOut is not token0 we should quote it to token0 value _reserveBaseValue = vSwapLibrary.quote( _reserveBaseValue, pairBalance1, pairBalance0 ); } unchecked { reservesBaseValueSum += _reserveBaseValue; reservesBaseValueSum -= reservesBaseValue[vPool.token1]; } reservesBaseValue[vPool.token1] = _reserveBaseValue; //update reserve balance reserves[vPool.token1] = reserveTokenBalance; } _update(uint112(fetchBalance(token0)), uint112(fetchBalance(token1))); emit ReserveSync( vPool.token1, reserves[vPool.token1], calculateReserveRatio() ); emit SwapReserve( msg.sender, vPool.token0, vPool.token1, requiredAmountIn, amountOut, ikPair, to ); } function allowListLength() external view returns (uint) { return allowList.length; } function liquidateReserve( address reserveToken, address nativePool ) external override nonReentrant { require( (msg.sender == IvPairFactory(factory).admin() && calculateReserveRatio() >= reserveRatioWarningThreshold) || msg.sender == IvPairFactory(factory).emergencyAdmin(), 'OA' ); require(allowListMap[reserveToken], 'TNW'); (address nativeToken0, address nativeToken1) = IvPair(nativePool) .getTokens(); (uint256 nativeBalance0, uint256 nativeBalance1) = IvPair(nativePool) .getBalances(); if (nativeToken0 != reserveToken) { (nativeToken0, nativeToken1) = (nativeToken1, nativeToken0); (nativeBalance0, nativeBalance1) = (nativeBalance1, nativeBalance0); } uint256 reserveAmount = reserves[reserveToken]; require( (nativeToken1 == token0 || nativeToken1 == token1) && IvPairFactory(factory).pairs(reserveToken, nativeToken1) == nativePool, 'INP' ); unchecked { reservesBaseValueSum -= reservesBaseValue[reserveToken]; } reservesBaseValue[reserveToken] = 0; reserves[reserveToken] = 0; SafeERC20.safeTransfer(IERC20(reserveToken), nativePool, reserveAmount); IvPair(nativePool).swapNative( vSwapLibrary.getAmountOut( reserveAmount, nativeBalance0, nativeBalance1, IvPair(nativePool).fee() ), nativeToken1, address(this), new bytes(0) ); _update(uint112(fetchBalance(token0)), uint112(fetchBalance(token1))); emit ReserveSync(reserveToken, 0, calculateReserveRatio()); } function swapReserveToNative( uint256 amountOut, address ikPair, address to, bytes calldata data ) external override nonReentrant isOpen returns (uint256 amountIn) { require(amountOut > 0, 'IAO'); require(to > address(0) && to != token0 && to != token1, 'IT'); VirtualPoolModel memory vPool = IvPoolManager( IvPairFactory(factory).vPoolManager() ).getVirtualPool(address(this), ikPair); // validate ikPair with factory require( IvPairFactory(factory).pairs(vPool.token0, vPool.commonToken) == ikPair, 'IIKP' ); require(amountOut < vPool.balance1, 'AOE'); uint256 requiredAmountIn = vSwapLibrary.getAmountIn( amountOut, vPool.balance0, vPool.balance1, vFee ); SafeERC20.safeTransfer(IERC20(vPool.token1), to, amountOut); if (data.length > 0) IvFlashSwapCallback(msg.sender).vFlashSwapCallback( vPool.token0, vPool.token1, requiredAmountIn, data ); uint256 tokenInBalance = fetchBalance(vPool.token0); amountIn = tokenInBalance - reserves[vPool.token0]; require(amountIn >= requiredAmountIn, 'IIA'); { //update reserve balance in the equivalent of token0 value //re-calculate price of reserve asset in token0 for the whole pool blance uint256 _reserveBaseValue = vSwapLibrary.quote( tokenInBalance, vPool.balance0, vPool.balance1 ); if (vPool.token1 == token1) { //if tokenOut is not token0 we should quote it to token0 value _reserveBaseValue = vSwapLibrary.quote( _reserveBaseValue, pairBalance1, pairBalance0 ); } unchecked { reservesBaseValueSum += _reserveBaseValue; reservesBaseValueSum -= reservesBaseValue[vPool.token0]; } reservesBaseValue[vPool.token0] = _reserveBaseValue; } //update reserve balance reserves[vPool.token0] = tokenInBalance; _update(uint112(fetchBalance(token0)), uint112(fetchBalance(token1))); uint256 reserveRatio = calculateReserveRatio(); require(reserveRatio <= maxReserveRatio, 'TBPT'); // reserve amount goes beyond pool threshold IvPoolManager(IvPairFactory(factory).vPoolManager()) .updateVirtualPoolBalances( address(this), ikPair, vPool.balance0 + amountIn, vPool.balance1 - amountOut ); emit ReserveSync(vPool.token0, tokenInBalance, reserveRatio); emit SwapReserve( msg.sender, vPool.token0, vPool.token1, requiredAmountIn, amountOut, ikPair, to ); } function calculateReserveRatio() public view override returns (uint256 rRatio) { uint256 _pairBalance0 = pairBalance0; rRatio = _pairBalance0 > 0 ? (reservesBaseValueSum * RESERVE_RATIO_FACTOR) / (_pairBalance0 << 1) : 0; } function mint( address to ) external override nonReentrant isOpen returns (uint256 liquidity) { (uint256 _pairBalance0, uint256 _pairBalance1) = ( pairBalance0, pairBalance1 ); uint256 currentBalance0 = fetchBalance(token0); uint256 currentBalance1 = fetchBalance(token1); uint256 amount0 = currentBalance0 - _pairBalance0; uint256 amount1 = currentBalance1 - _pairBalance1; uint256 totalSupply_ = totalSupply(); if (totalSupply_ == 0) { liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { liquidity = Math.min( (amount0 * totalSupply_) / _pairBalance0, (amount1 * totalSupply_) / _pairBalance1 ); } //substract reserve ratio PCT from minted liquidity tokens amount uint256 reserveRatio = calculateReserveRatio(); liquidity = (liquidity * RESERVE_RATIO_FACTOR) / (RESERVE_RATIO_FACTOR + reserveRatio); require(liquidity > 0, 'ILM'); _mint(to, liquidity); _update(uint112(currentBalance0), uint112(currentBalance1)); emit Mint(to, amount0, amount1, liquidity, totalSupply()); } function burn( address to ) external override nonReentrant returns (uint256 amount0, uint256 amount1) { address _token0 = token0; // gas savings address _token1 = token1; // gas savings uint256 balance0 = fetchBalance(_token0); uint256 balance1 = fetchBalance(_token1); uint256 liquidity = fetchBalance(address(this)); uint256 totalSupply_ = totalSupply(); amount0 = (balance0 * liquidity) / totalSupply_; amount1 = (balance1 * liquidity) / totalSupply_; require(amount0 > 0 && amount1 > 0, 'ILB'); _burn(address(this), liquidity); SafeERC20.safeTransfer(IERC20(_token0), to, amount0); SafeERC20.safeTransfer(IERC20(_token1), to, amount1); //distribute reserve tokens and update reserve ratios uint256 _currentReserveRatio = calculateReserveRatio(); if (_currentReserveRatio > 0) { for (uint256 i = 0; i < allowList.length; ++i) { address _wlI = allowList[i]; uint256 reserveBalance = reserves[_wlI]; if (reserveBalance > 0) { uint256 reserveAmountOut = (reserveBalance * liquidity) / totalSupply_; SafeERC20.safeTransfer(IERC20(_wlI), to, reserveAmountOut); uint256 reserveBaseValuewlI = reservesBaseValue[_wlI]; //gas saving reservesBaseValue[_wlI] = reserveBaseValuewlI - ((reserveBaseValuewlI * liquidity) / totalSupply_); unchecked { reservesBaseValueSum += reservesBaseValue[_wlI]; reservesBaseValueSum -= reserveBaseValuewlI; } reserves[_wlI] = reserveBalance - reserveAmountOut; } } } balance0 = fetchBalance(_token0); balance1 = fetchBalance(_token1); _update(uint112(balance0), uint112(balance1)); emit Burn(msg.sender, amount0, amount1, to, totalSupply()); } function setAllowList(address[] memory _allowList) external override { require( msg.sender == factory || msg.sender == IvPairFactory(factory).admin() || msg.sender == IvPairFactory(factory).emergencyAdmin(), 'OA' ); for (uint i = 1; i < _allowList.length; ++i) { require( _allowList[i] > _allowList[i - 1], 'allow list must be unique and sorted' ); } address[] memory _oldWL = allowList; for (uint256 i = 0; i < _oldWL.length; ++i) allowListMap[_oldWL[i]] = false; //set new allowList allowList = _allowList; address token0_ = token0; address token1_ = token1; uint256 newReservesBaseValueSum; for (uint256 i = 0; i < _allowList.length; ++i) if (_allowList[i] != token0_ && _allowList[i] != token1_) { allowListMap[_allowList[i]] = true; newReservesBaseValueSum += reservesBaseValue[_allowList[i]]; } reservesBaseValueSum = newReservesBaseValueSum; emit AllowListChanged(_allowList); } function setFee( uint16 _fee, uint16 _vFee ) external override onlyFactoryAdmin { require(_fee > 0 && _vFee > 0 && _fee < 1000 && _vFee < 1000, 'IFC'); fee = _fee; vFee = _vFee; emit FeeChanged(_fee, _vFee); } function setMaxReserveThreshold( uint256 threshold ) external override onlyFactoryAdmin { require(threshold > 0, 'IRT'); maxReserveRatio = threshold; emit ReserveThresholdChanged(threshold); } function setReserveRatioWarningThreshold( uint256 _reserveRatioWarningThreshold ) external override onlyEmergencyAdmin { require(_reserveRatioWarningThreshold <= maxReserveRatio, 'IRWT'); reserveRatioWarningThreshold = _reserveRatioWarningThreshold; emit ReserveRatioWarningThresholdChanged(_reserveRatioWarningThreshold); } function emergencyToggle() external override onlyEmergencyAdmin { closed = !closed; } function setBlocksDelay(uint128 _newBlocksDelay) external override { require( msg.sender == IvPairFactory(factory).emergencyAdmin() || msg.sender == IvPairFactory(factory).admin(), 'OA' ); blocksDelay = _newBlocksDelay; emit BlocksDelayChanged(_newBlocksDelay); } function reserveRatioFactor() external pure override returns (uint256) { return RESERVE_RATIO_FACTOR; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; struct MaxTradeAmountParams { uint256 fee; uint256 balance0; uint256 balance1; uint256 vBalance0; uint256 vBalance1; uint256 reserveRatioFactor; uint256 priceFeeFactor; uint256 maxReserveRatio; uint256 reserves; uint256 reservesBaseValueSum; } struct VirtualPoolModel { uint24 fee; address token0; address token1; uint256 balance0; uint256 balance1; address commonToken; address jkPair; address ikPair; } struct VirtualPoolTokens { address jk0; address jk1; address ik0; address ik1; } struct ExchangeReserveCallbackParams { address jkPair1; address ikPair1; address jkPair2; address ikPair2; address caller; uint256 flashAmountOut; } struct SwapCallbackData { address caller; uint256 tokenInMax; uint ETHValue; address jkPool; } struct PoolCreationDefaults { address factory; address token0; address token1; uint16 fee; uint16 vFee; uint256 maxReserveRatio; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; /// @title Provides functions for deriving a pool address from the factory and token library PoolAddress { bytes32 internal constant POOL_INIT_CODE_HASH = 0x637bc1e6555f050fef1c3804f2f03647a960ac0a39ac52c519c3c6d9da312ae0; function orderAddresses( address tokenA, address tokenB ) internal pure returns (address token0, address token1) { return (tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA)); } function getSalt( address tokenA, address tokenB ) internal pure returns (bytes32 salt) { (address token0, address token1) = orderAddresses(tokenA, tokenB); salt = keccak256(abi.encode(token0, token1)); } function computeAddress( address factory, address token0, address token1 ) internal pure returns (address pool) { bytes32 _salt = getSalt(token0, token1); pool = address( uint160( uint256( keccak256( abi.encodePacked( bytes1(0xff), factory, _salt, POOL_INIT_CODE_HASH ) ) ) ) ); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import '../types.sol'; interface IvPair { event TestEvent( VirtualPoolModel vPool, uint256 amountIn, uint256 maxTradeAmount ); event Mint( address indexed sender, uint256 amount0, uint256 amount1, uint lpTokens, uint poolLPTokens ); event Burn( address indexed sender, uint256 amount0, uint256 amount1, address indexed to, uint256 totalSupply ); event Swap( address indexed sender, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut, address indexed to ); event SwapReserve( address indexed sender, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut, address ikPool, address indexed to ); event AllowListChanged(address[] tokens); event vSync(uint112 balance0, uint112 balance1); event ReserveSync(address asset, uint256 balance, uint256 rRatio); event FeeChanged(uint16 fee, uint16 vFee); event ReserveThresholdChanged(uint256 newThreshold); event BlocksDelayChanged(uint256 _newBlocksDelay); event ReserveRatioWarningThresholdChanged( uint256 _newReserveRatioWarningThreshold ); function fee() external view returns (uint16); function vFee() external view returns (uint16); function setFee(uint16 _fee, uint16 _vFee) external; function swapNative( uint256 amountOut, address tokenOut, address to, bytes calldata data ) external returns (uint256 _amountIn); function swapReserveToNative( uint256 amountOut, address ikPair, address to, bytes calldata data ) external returns (uint256 _amountIn); function swapNativeToReserve( uint256 amountOut, address ikPair, address to, uint256 incentivesLimitPct, bytes calldata data ) external returns (address _token, uint256 _leftovers); function liquidateReserve( address reserveToken, address nativePool ) external; function mint(address to) external returns (uint256 liquidity); function burn( address to ) external returns (uint256 amount0, uint256 amount1); function setAllowList(address[] memory _allowList) external; function allowListMap(address _token) external view returns (bool allowed); function calculateReserveRatio() external view returns (uint256 rRatio); function setMaxReserveThreshold(uint256 threshold) external; function setReserveRatioWarningThreshold(uint256 threshold) external; function setBlocksDelay(uint128 _newBlocksDelay) external; function emergencyToggle() external; function allowListLength() external view returns (uint); function token0() external view returns (address); function token1() external view returns (address); function pairBalance0() external view returns (uint112); function pairBalance1() external view returns (uint112); function maxReserveRatio() external view returns (uint256); function getBalances() external view returns (uint112, uint112); function lastSwapBlock() external view returns (uint128); function blocksDelay() external view returns (uint128); function getTokens() external view returns (address, address); function reservesBaseValue( address reserveAddress ) external view returns (uint256); function reserves(address reserveAddress) external view returns (uint256); function reservesBaseValueSum() external view returns (uint256); function reserveRatioFactor() external pure returns (uint256); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import './IvFlashSwapCallback.sol'; interface IvExchangeReserves is IvFlashSwapCallback { event ReservesExchanged( address jkPair1, address ikPair1, address jkPair2, address ikPair2, uint256 requiredBackAmount, uint256 flashAmountOut, address leftOverToken, uint leftOverAmount ); event NewIncentivesLimit(uint256 newLimit); function factory() external view returns (address); function exchange( address jkPair1, address ikPair1, address jkPair2, address ikPair2, uint256 flashAmountOut ) external; function changeIncentivesLimitPct(uint256 newLimit) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; /// @title An interface for a contract that is capable of deploying Uniswap V3 Pools /// @notice A contract that constructs a pool must implement this to pass arguments to the pool /// @dev This is used to avoid having constructor arguments in the pool contract, which results in the init code hash /// of the pool being constant allowing the CREATE2 address of the pool to be cheaply computed on-chain interface IvSwapPoolDeployer { /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation. /// @dev Called by the pool constructor to fetch the parameters of the pool /// Returns factory The factory address /// Returns token0 The first token of the pool by address sort order /// Returns token1 The second token of the pool by address sort order /// Returns fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// Returns tickSpacing The minimum number of ticks between initialized ticks function poolCreationDefaults() external view returns ( address factory, address token0, address token1, uint16 fee, uint16 vFee, uint256 maxReserveRatio ); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; interface IvPairFactory { event PairCreated( address poolAddress, address factory, address token0, address token1, uint16 fee, uint16 vFee, uint256 maxReserveRatio ); event DefaultAllowListChanged(address[] allowList); event FactoryNewAdmin(address newAdmin); event FactoryNewPendingAdmin(address newPendingAdmin); event FactoryNewEmergencyAdmin(address newEmergencyAdmin); event FactoryNewPendingEmergencyAdmin(address newPendingEmergencyAdmin); event ExchangeReserveAddressChanged(address newExchangeReserve); event FactoryVPoolManagerChanged(address newVPoolManager); function createPair( address tokenA, address tokenB ) external returns (address); function pairs( address tokenA, address tokenB ) external view returns (address); function setDefaultAllowList(address[] calldata _defaultAllowList) external; function allPairs(uint256 index) external view returns (address); function allPairsLength() external view returns (uint256); function vPoolManager() external view returns (address); function admin() external view returns (address); function emergencyAdmin() external view returns (address); function pendingEmergencyAdmin() external view returns (address); function setPendingEmergencyAdmin(address newEmergencyAdmin) external; function acceptEmergencyAdmin() external; function pendingAdmin() external view returns (address); function setPendingAdmin(address newAdmin) external; function setVPoolManagerAddress(address _vPoolManager) external; function acceptAdmin() external; function exchangeReserves() external view returns (address); function setExchangeReservesAddress(address _exchangeReserves) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns the balance of a token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) pragma solidity 0.8.18; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol'; import '@openzeppelin/contracts/utils/Context.sol'; import '@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol'; //for test /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract vSwapERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private constant _name = 'Virtuswap-LP'; string private constant _symbol = 'VSWAPLP'; /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf( address account ) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer( address to, uint256 amount ) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance( address owner, address spender ) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve( address spender, uint256 amount ) external virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance( address spender, uint256 addedValue ) external virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance( address spender, uint256 subtractedValue ) external virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require( currentAllowance >= subtractedValue, 'ERC20: decreased allowance below zero' ); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), 'ERC20: transfer from the zero address'); require(to != address(0), 'ERC20: transfer to the zero address'); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require( fromBalance >= amount, 'ERC20: transfer amount exceeds balance' ); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), 'ERC20: burn from the zero address'); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, 'ERC20: burn amount exceeds balance'); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), 'ERC20: approve from the zero address'); require(spender != address(0), 'ERC20: approve to the zero address'); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require( currentAllowance >= amount, 'ERC20: insufficient allowance' ); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import '../types.sol'; interface IvPoolManager { function pairFactory() external view returns (address); function getVirtualPool( address jkPair, address ikPair ) external view returns (VirtualPoolModel memory vPool); function getVirtualPools( address token0, address token1 ) external view returns (VirtualPoolModel[] memory vPools); function updateVirtualPoolBalances( address jkPair, address ikPair, uint256 balance0, uint256 balance1 ) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; interface IvFlashSwapCallback { function vFlashSwapCallback( address tokenIn, address tokenOut, uint256 requiredBackAmount, bytes calldata data ) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.18; import '@openzeppelin/contracts/utils/math/Math.sol'; import '@openzeppelin/contracts/utils/math/SafeCast.sol'; import '../types.sol'; import '../interfaces/IvPair.sol'; library vSwapLibrary { uint24 internal constant PRICE_FEE_FACTOR = 10 ** 3; //find common token and assign to ikToken1 and jkToken1 function findCommonToken( address ikToken0, address ikToken1, address jkToken0, address jkToken1 ) internal pure returns (VirtualPoolTokens memory vPoolTokens) { ( vPoolTokens.ik0, vPoolTokens.ik1, vPoolTokens.jk0, vPoolTokens.jk1 ) = (ikToken0 == jkToken0) ? (ikToken1, ikToken0, jkToken1, jkToken0) : (ikToken0 == jkToken1) ? (ikToken1, ikToken0, jkToken0, jkToken1) : (ikToken1 == jkToken0) ? (ikToken0, ikToken1, jkToken1, jkToken0) : (ikToken0, ikToken1, jkToken0, jkToken1); //default } function calculateVPool( uint256 ikTokenABalance, uint256 ikTokenBBalance, uint256 jkTokenABalance, uint256 jkTokenBBalance ) internal pure returns (VirtualPoolModel memory vPool) { vPool.balance0 = (ikTokenABalance * Math.min(ikTokenBBalance, jkTokenBBalance)) / Math.max(ikTokenBBalance, 1); vPool.balance1 = (jkTokenABalance * Math.min(ikTokenBBalance, jkTokenBBalance)) / Math.max(jkTokenBBalance, 1); } function getAmountIn( uint256 amountOut, uint256 pairBalanceIn, uint256 pairBalanceOut, uint256 fee ) internal pure returns (uint256 amountIn) { uint256 numerator = (pairBalanceIn * amountOut) * PRICE_FEE_FACTOR; uint256 denominator = (pairBalanceOut - amountOut) * fee; amountIn = (numerator / denominator) + 1; } function getAmountOut( uint256 amountIn, uint256 pairBalanceIn, uint256 pairBalanceOut, uint256 fee ) internal pure returns (uint256 amountOut) { uint256 amountInWithFee = amountIn * fee; uint256 numerator = amountInWithFee * pairBalanceOut; uint256 denominator = (pairBalanceIn * PRICE_FEE_FACTOR) + amountInWithFee; amountOut = numerator / denominator; } function quote( uint256 amountA, uint256 balanceA, uint256 balanceB ) internal pure returns (uint256 amountB) { require(amountA > 0, 'VSWAP: INSUFFICIENT_AMOUNT'); require(balanceA > 0 && balanceB > 0, 'VSWAP: INSUFFICIENT_LIQUIDITY'); amountB = (amountA * balanceB) / balanceA; } function sortBalances( address tokenIn, address baseToken, uint256 pairBalance0, uint256 pairBalance1 ) internal pure returns (uint256 _balance0, uint256 _balance1) { (_balance0, _balance1) = baseToken == tokenIn ? (pairBalance0, pairBalance1) : (pairBalance1, pairBalance0); } function getVirtualPool( address jkPair, address ikPair ) internal view returns (VirtualPoolModel memory vPool) { require( block.number >= IvPair(ikPair).lastSwapBlock() + IvPair(ikPair).blocksDelay(), 'VSWAP: LOCKED_VPOOL' ); (address jk0, address jk1) = IvPair(jkPair).getTokens(); (address ik0, address ik1) = IvPair(ikPair).getTokens(); VirtualPoolTokens memory vPoolTokens = findCommonToken( ik0, ik1, jk0, jk1 ); require( (vPoolTokens.ik0 != vPoolTokens.jk0) && (vPoolTokens.ik1 == vPoolTokens.jk1), 'VSWAP: INVALID_VPOOL' ); (uint256 ikBalance0, uint256 ikBalance1) = IvPair(ikPair).getBalances(); (uint256 jkBalance0, uint256 jkBalance1) = IvPair(jkPair).getBalances(); vPool = calculateVPool( vPoolTokens.ik0 == ik0 ? ikBalance0 : ikBalance1, vPoolTokens.ik0 == ik0 ? ikBalance1 : ikBalance0, vPoolTokens.jk0 == jk0 ? jkBalance0 : jkBalance1, vPoolTokens.jk0 == jk0 ? jkBalance1 : jkBalance0 ); vPool.token0 = vPoolTokens.ik0; vPool.token1 = vPoolTokens.jk0; vPool.commonToken = vPoolTokens.ik1; require( IvPair(jkPair).allowListMap(vPool.token0), 'VSWAP: NOT_ALLOWED' ); vPool.fee = IvPair(jkPair).vFee(); vPool.jkPair = jkPair; vPool.ikPair = ikPair; } /** @dev The function is used to calculate maximum virtual trade amount for * swapReserveToNative. The maximum amount that can be traded is such that * after the swap reserveRatio will be equal to maxReserveRatio: * * (reserveBaseValueSum + newReserveBaseValue(vPool.token0)) * reserveRatioFactor / (2 * balance0) = maxReserveRatio, * where balance0 is the balance of token0 after the swap (i.e. oldBalance0 + amountOut), * reserveBaseValueSum is SUM(reserveBaseValue[i]) without reserveBaseValue(vPool.token0) * newReserveBaseValue(vPool.token0) is reserveBaseValue(vPool.token0) after the swap * * amountOut can be expressed through amountIn: * amountOut = (amountIn * fee * vBalance1) / (amountIn * fee + vBalance0 * priceFeeFactor) * * reserveBaseValue(vPool.token0) can be expessed as: * if vPool.token1 == token0: * reserveBaseValue(vPool.token0) = reserves[vPool.token0] * vBalance1 / vBalance0 * else: * reserveBaseValue(vPool.token0) = (reserves[vPool.token0] * vBalance1 * balance0) / (vBalance0 * balance1) * * Given all that we have two equations for finding maxAmountIn: * if vPool.token1 == token0: * Ax^2 + Bx + C = 0, * where A = fee * reserveRatioFactor * vBalance1, * B = vBalance0 * (-2 * balance0 * fee * maxReserveRatio + vBalance1 * * (2 * fee * maxReserveRatio + priceFeeFactor * reserveRatioFactor) + * fee * reserveRatioFactor * reservesBaseValueSum) + * fee * reserves * reserveRatioFactor * vBalance1, * C = -priceFeeFactor * balance0 * (2 * balance0 * maxReserveRatio * vBalance0 - * reserveRatioFactor * (reserves * vBalance1 + reservesBaseValueSum * vBalance0)); * if vPool.token1 == token1: * x = balance1 * vBalance0 * (2 * balance0 * maxReserveRatio - reserveRatioFactor * reservesBaseValueSum) / * (balance0 * reserveRatioFactor * vBalance1) * * In the first case, we solve quadratic equation using Newton method. */ function getMaxVirtualTradeAmountRtoN( VirtualPoolModel memory vPool ) internal view returns (uint256) { // The function works if and only if the following constraints are // satisfied: // 1. all balances are positive and less than or equal to 10^32 // 2. reserves are non-negative and less than or equal to 10^32 // 3. 0 < vBalance1 <= balance0 (or balance1 depending on trade) // 4. priceFeeFactor == 10^3 // 5. reserveRatioFactor == 10^5 // 6. 0 < fee <= priceFeeFactor // 7. 0 < maxReserveRatio <= reserveRatioFactor // 8. reserveBaseValueSum <= 2 * balance0 * maxReserveRatio (see // reserve ratio formula in vPair.calculateReserveRatio()) MaxTradeAmountParams memory params; params.fee = uint256(vPool.fee); params.balance0 = IvPair(vPool.jkPair).pairBalance0(); params.balance1 = IvPair(vPool.jkPair).pairBalance1(); params.vBalance0 = vPool.balance0; params.vBalance1 = vPool.balance1; params.reserveRatioFactor = IvPair(vPool.jkPair).reserveRatioFactor(); params.priceFeeFactor = uint256(PRICE_FEE_FACTOR); params.maxReserveRatio = IvPair(vPool.jkPair).maxReserveRatio(); params.reserves = IvPair(vPool.jkPair).reserves(vPool.token0); params.reservesBaseValueSum = IvPair(vPool.jkPair).reservesBaseValueSum() - IvPair(vPool.jkPair).reservesBaseValue(vPool.token0); require( params.balance0 > 0 && params.balance0 <= 10 ** 32, 'invalid balance0' ); require( params.balance1 > 0 && params.balance1 <= 10 ** 32, 'invalid balance1' ); require( params.vBalance0 > 0 && params.vBalance0 <= 10 ** 32, 'invalid vBalance0' ); require( params.vBalance1 > 0 && params.vBalance1 <= 10 ** 32, 'invalid vBalance1' ); require(params.priceFeeFactor == 10 ** 3, 'invalid priceFeeFactor'); require( params.reserveRatioFactor == 10 ** 5, 'invalid reserveRatioFactor' ); require( params.fee > 0 && params.fee <= params.priceFeeFactor, 'invalid fee' ); require( params.maxReserveRatio > 0 && params.maxReserveRatio <= params.reserveRatioFactor, 'invalid maxReserveRatio' ); // reserves are full, the answer is 0 if ( params.reservesBaseValueSum > 2 * params.balance0 * params.maxReserveRatio ) return 0; int256 maxAmountIn; if (IvPair(vPool.jkPair).token0() == vPool.token1) { require(params.vBalance1 <= params.balance0, 'invalid vBalance1'); unchecked { // a = R * v1 <= 10^5 * v1 = 10^5 * v1 <= 10^37 uint256 a = params.vBalance1 * params.reserveRatioFactor; // b = v0 * (-2 * b0 * M + v1 * (2 * M + R * F / f) + R * s) + r * R * v1 <= // <= v0 * (-2 * b0 * M + b0 * (2 * M + 10^8) + 10^5 * s) + 10^5 * r * v1 = // = v0 * (10^8 * b0 + 10^5 * s) + 10^5 * r * v1 = // = 10^5 * (v0 * (10^3 * b0 + s) + r * v1) <= // <= 10^5 * (v0 * (10^3 * b0 + 2 * b0 * M) + r * v1) <= // <= 10^5 * (v0 * (10^3 * b0 + 2 * 10^5 * b0) + r * v1) = // = 10^5 * (v0 * b0 * (2 * 10^5 + 10^3) + r * v1) <= // <= 10^5 * (10^64 * 2 * 10^5 + 10^64) <= 2 * 10^74 int256 b = int256(params.vBalance0) * (-2 * int256(params.balance0 * params.maxReserveRatio) + int256( params.vBalance1 * (2 * params.maxReserveRatio + (params.priceFeeFactor * params.reserveRatioFactor) / params.fee) + params.reserveRatioFactor * params.reservesBaseValueSum )) + int256( params.reserves * params.reserveRatioFactor * params.vBalance1 ); // we split C into c1 * c2 to fit in uint256 // c1 = F * v0 / f <= 10^3 * v0 <= 10^35 uint256 c1 = (params.priceFeeFactor * params.vBalance0) / params.fee; // c2 = 2 * b0 * M * v0 - R * (r * v1 + s * v0) <= // <= [r and s can be zero] <= // <= 2 * 10^5 * b0 * v0 - 0 <= 2 * 10^69 // // -c2 = R * (r * v1 + s * v0) - 2 * b0 * M * v0 <= // <= 10^5 * (r * v1 + 2 * b0 * M * v0) - 2 * b0 * M * v0 = // = 10^5 * r * v1 + 2 * b0 * M * v0 * (10^5 - 1) <= // <= 10^5 * 10^32 * 10^32 + 2 * 10^32 * 10^5 * 10^32 * 10^5 <= // <= 10^69 + 2 * 10^74 <= 2 * 10^74 // // |c2| <= 2 * 10^74 int256 c2 = 2 * int256( params.balance0 * params.maxReserveRatio * params.vBalance0 ) - int256( params.reserveRatioFactor * (params.reserves * params.vBalance1 + params.reservesBaseValueSum * params.vBalance0) ); (bool negativeC, uint256 uc2) = ( c2 < 0 ? (false, uint256(-c2)) : (true, uint256(c2)) ); // according to Newton's method: // x_{n+1} = x_n - f(x_n) / f'(x_n) = // = x_n - (Ax_n^2 + Bx_n + c1 * c2) / (2Ax_n + B) = // = (2Ax_n^2 + Bx_n - Ax_n^2 - Bx_n - c1 * c2) / (2Ax_n + B) = // = (Ax_n^2 - c1 * c2) / (2Ax_n + B) = // = Ax_n^2 / (2Ax_n + B) - c1 * c2 / (2Ax_n + B) // initial approximation: maxAmountIn always <= vb0 maxAmountIn = int256(params.vBalance0); // derivative = 2 * a * x + b = // = 2 * R * f * v1 * x + v0 * (-2 * b0 * f * M + v1 * (2 * f * M + R * F) + f * R * s) + f * r * R * v1 <= // <= 2 * 10^40 * 10^32 + 2 * 10^76 <= 2 * 10^76 int256 derivative = int256(2 * a) * maxAmountIn + b; (bool negativeDerivative, uint256 uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); // maxAmountIn * maxAmountIn <= vb0 * vb0 <= 10^64 maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; derivative = int256(2 * a) * maxAmountIn + b; (negativeDerivative, uDerivative) = ( derivative < 0 ? (true, uint256(-derivative)) : (false, uint256(derivative)) ); maxAmountIn = ( negativeC ? SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) + SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) : SafeCast.toInt256( Math.mulDiv( a, uint256(maxAmountIn * maxAmountIn), uDerivative ) ) - SafeCast.toInt256(Math.mulDiv(c1, uc2, uDerivative)) ); if (negativeDerivative) maxAmountIn = -maxAmountIn; } } else { unchecked { require( params.vBalance1 <= params.balance1, 'invalid vBalance1' ); maxAmountIn = SafeCast.toInt256( Math.mulDiv( params.balance1 * params.vBalance0, 2 * params.balance0 * params.maxReserveRatio - params.reserveRatioFactor * params.reservesBaseValueSum, params.balance0 * params.reserveRatioFactor * params.vBalance1 ) ) - SafeCast.toInt256(params.reserves); } } assert(maxAmountIn >= 0); return uint256(maxAmountIn); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// 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 (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetFixedSupply.sol) pragma solidity ^0.8.0; import "../extensions/ERC20Burnable.sol"; /** * @dev {ERC20} token, including: * * - Preminted initial supply * - Ability for holders to burn (destroy) their tokens * - No access control mechanism (for minting/pausing) and hence no governance * * This contract uses {ERC20Burnable} to include burn capabilities - head to * its documentation for details. * * _Available since v3.4._ * * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._ */ contract ERC20PresetFixedSupply is ERC20Burnable { /** * @dev Mints `initialSupply` amount of token and transfers them to `owner`. * * See {ERC20-constructor}. */ constructor( string memory name, string memory symbol, uint256 initialSupply, address owner ) ERC20(name, symbol) { _mint(owner, initialSupply); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { _spendAllowance(account, _msgSender(), amount); _burn(account, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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://diligence.consensys.net/posts/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 (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); }
{ "optimizer": { "enabled": true, "runs": 833 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"allowList","type":"address[]"}],"name":"DefaultAllowListChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newExchangeReserve","type":"address"}],"name":"ExchangeReserveAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"FactoryNewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newEmergencyAdmin","type":"address"}],"name":"FactoryNewEmergencyAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"FactoryNewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPendingEmergencyAdmin","type":"address"}],"name":"FactoryNewPendingEmergencyAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newVPoolManager","type":"address"}],"name":"FactoryVPoolManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"uint16","name":"fee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"vFee","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"maxReserveRatio","type":"uint256"}],"name":"PairCreated","type":"event"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptEmergencyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeReserves","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"pairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingEmergencyAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolCreationDefaults","outputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint16","name":"fee","type":"uint16"},{"internalType":"uint16","name":"vFee","type":"uint16"},{"internalType":"uint256","name":"maxReserveRatio","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_defaultAllowList","type":"address[]"}],"name":"setDefaultAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exchangeReserves","type":"address"}],"name":"setExchangeReservesAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingEmergencyAdmin","type":"address"}],"name":"setPendingEmergencyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vPoolManager","type":"address"}],"name":"setVPoolManagerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vPoolManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5060028054336001600160a01b03199182168117909255600480549091169091179055615f9a806100426000396000f3fe60806040523480156200001157600080fd5b50600436106200014f5760003560e01c80636d495f8311620000c0578063b5358fab116200008b578063c9c65396116200006e578063c9c65396146200034e578063f851a4401462000365578063fea77eae146200037957600080fd5b8063b5358fab1462000323578063c4ce80d1146200033757600080fd5b80636d495f8314620002ca57806370905dce14620002e15780638d018b4d14620002f5578063ad4d1ee5146200030c57600080fd5b806337e0376b116200011e578063574f2ba31162000101578063574f2ba3146200027a5780635e278915146200028c57806369454b86146200029657600080fd5b806337e0376b146200024f5780634dd18bf5146200026357600080fd5b80630d19c79d14620001545780630e18b68114620001ff5780631e3dd18b146200020b57806326782247146200023b575b600080fd5b600954600a54600b54600c54620001b5936001600160a01b03908116938116929081169161ffff7401000000000000000000000000000000000000000083048116927601000000000000000000000000000000000000000000009004169086565b604080516001600160a01b0397881681529587166020870152939095169284019290925261ffff908116606084015216608082015260a081019190915260c0015b60405180910390f35b620002096200038d565b005b620002226200021c36600462000f96565b62000432565b6040516001600160a01b039091168152602001620001f6565b60035462000222906001600160a01b031681565b60075462000222906001600160a01b031681565b620002096200027436600462000fc9565b6200045d565b600154604051908152602001620001f6565b62000209620004f3565b62000222620002a736600462000ff0565b60006020818152928152604080822090935290815220546001600160a01b031681565b62000209620002db36600462000fc9565b6200058f565b60045462000222906001600160a01b031681565b62000209620003063660046200102e565b62000727565b620002096200031d36600462000fc9565b620008bc565b60055462000222906001600160a01b031681565b620002096200034836600462000fc9565b6200094d565b620002226200035f36600462000ff0565b62000acb565b60025462000222906001600160a01b031681565b60065462000222906001600160a01b031681565b6003546001600160a01b03163314620003d35760405162461bcd60e51b81526020600482015260036024820152624f504160e81b60448201526064015b60405180910390fd5b60038054600280546001600160a01b0383166001600160a01b031991821681179092559091169091556040519081527f49979123b2bc91263f3f2f1a87e92ce0e486c6c70943d1d67f8beee550efb663906020015b60405180910390a1565b600181815481106200044357600080fd5b6000918252602090912001546001600160a01b0316905081565b6002546001600160a01b031633146200049e5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f07a0003b2bc46a6950059c8ae85d2c7e50e9b46f922fe6aba4317d26f2f6f0f9906020015b60405180910390a150565b6005546001600160a01b03163314620005355760405162461bcd60e51b81526020600482015260036024820152624f504160e81b6044820152606401620003ca565b60058054600480546001600160a01b0383166001600160a01b031991821681179092559091169091556040519081527f4e08187fea80af9168fe976bfc7234414071130284ac83e2a6563750f74a2cf39060200162000428565b6002546001600160a01b03163314620005d05760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b6001600160a01b038116620006285760405162461bcd60e51b815260206004820152600560248201527f4956504d410000000000000000000000000000000000000000000000000000006044820152606401620003ca565b306001600160a01b0316816001600160a01b031663e14f870d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000671573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006979190620010a8565b6001600160a01b031614620006d85760405162461bcd60e51b8152600401620003ca906020808252600490820152634956504d60e01b604082015260600190565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fe823a8e80e62dc26cf857355ee4f23825d6881b26707a1a9a9b3248ac3af0aec90602001620004e8565b6002546001600160a01b03163314620007685760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b62ffffff811115620007a35760405162461bcd60e51b815260206004820152600360248201526210551360ea1b6044820152606401620003ca565b60015b818110156200086d578282620007be600184620010de565b818110620007d057620007d0620010f4565b9050602002016020810190620007e7919062000fc9565b6001600160a01b0316838383818110620008055762000805620010f4565b90506020020160208101906200081c919062000fc9565b6001600160a01b0316116200085a5760405162461bcd60e51b8152602060048201526003602482015262414c5560e81b6044820152606401620003ca565b62000865816200110a565b9050620007a6565b506200087c6008838362000f09565b507f3100a95101e6b59aeaea5117410f1539971c1536f72dc73ce806a450c85e394c8282604051620008b092919062001126565b60405180910390a15050565b6004546001600160a01b03163314620008fe5760405162461bcd60e51b81526020600482015260036024820152624f454160e81b6044820152606401620003ca565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527fe193ea528cfd9222d51ca7a5197c2f22df949ae773d1069cfabeffa68fe856bd90602001620004e8565b6002546001600160a01b031633146200098e5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b6001600160a01b038116620009cf5760405162461bcd60e51b8152600401620003ca906020808252600490820152634945524160e01b604082015260600190565b306001600160a01b0316816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a18573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a3e9190620010a8565b6001600160a01b03161462000a7c5760405162461bcd60e51b815260206004820152600360248201526224a2a960e91b6044820152606401620003ca565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f565432aa4b07668ec2d26adccb36e35bebdd6779cc94dca1f3b704e253b4010590602001620004e8565b6000816001600160a01b0316836001600160a01b03160362000b155760405162461bcd60e51b8152602060048201526002602482015261494160f01b6044820152606401620003ca565b60008062000b24858562000e87565b90925090506001600160a01b03821662000b665760405162461bcd60e51b81526020600482015260026024820152615a4160f01b6044820152606401620003ca565b6001600160a01b038281166000908152602081815260408083208585168452909152902054161562000bc05760405162461bcd60e51b8152602060048201526002602482015261504560f01b6044820152606401620003ca565b6040805160c081018252308082526001600160a01b03858116602084018190529085169383018490526103e56060840181905260808401526107d060a0909301839052600980546001600160a01b03199081169093179055600a8054909216179055600b80547fffffffffffffffffffff00000000000000000000000000000000000000000000169092177503e50000000000000000000000000000000000000000177fffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffff167703e50000000000000000000000000000000000000000000017909155600c55600062000cb3838362000eba565b90508060405162000cc49062000f71565b8190604051809103906000f590508015801562000ce5573d6000803e3d6000fd5b50600980546001600160a01b0319908116909155600a80549091169055600b80547fffffffffffffffff0000000000000000000000000000000000000000000000001690556000600c55604051636447c35d60e01b81529094506001600160a01b03851690636447c35d9062000d619060089060040162001178565b600060405180830381600087803b15801562000d7c57600080fd5b505af115801562000d91573d6000803e3d6000fd5b505050506001600160a01b0383811660008181526020818152604080832087861680855290835281842080546001600160a01b0319908116978c169788179091558484528285208686528452828520805482168817905560018054808201825595527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6909401805490941686179093558051948552309185019190915283019190915260608201526103e56080820181905260a08201526107d060c08201527f70084adbff44be952e8bb87558f46235532635d476e79e29558665fa7d6c12ce9060e00160405180910390a15050505b92915050565b600080826001600160a01b0316846001600160a01b03161062000eac57828462000eaf565b83835b915091509250929050565b600080600062000ecb858562000e87565b604080516001600160a01b03938416602080830191909152929093168382015280518084038201815260609093019052815191012095945050505050565b82805482825590600052602060002090810192821562000f5f579160200282015b8281111562000f5f5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019062000f2a565b5062000f6d92915062000f7f565b5090565b614dc380620011cb83390190565b5b8082111562000f6d576000815560010162000f80565b60006020828403121562000fa957600080fd5b5035919050565b6001600160a01b038116811462000fc657600080fd5b50565b60006020828403121562000fdc57600080fd5b813562000fe98162000fb0565b9392505050565b600080604083850312156200100457600080fd5b8235620010118162000fb0565b91506020830135620010238162000fb0565b809150509250929050565b600080602083850312156200104257600080fd5b823567ffffffffffffffff808211156200105b57600080fd5b818501915085601f8301126200107057600080fd5b8135818111156200108057600080fd5b8660208260051b85010111156200109657600080fd5b60209290920196919550909350505050565b600060208284031215620010bb57600080fd5b815162000fe98162000fb0565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000e815762000e81620010c8565b634e487b7160e01b600052603260045260246000fd5b6000600182016200111f576200111f620010c8565b5060010190565b60208082528181018390526000908460408401835b868110156200116d578235620011518162000fb0565b6001600160a01b0316825291830191908301906001016200113b565b509695505050505050565b6020808252825482820181905260008481528281209092916040850190845b81811015620011be5783546001600160a01b03168352600193840193928501920162001197565b5090969550505050505056fe60e06040523480156200001157600080fd5b506001600381905550336001600160a01b0316630d19c79d6040518163ffffffff1660e01b815260040160c060405180830381865afa15801562000059573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200007f91906200011d565b600755600480546001600160e01b0316600160f01b61ffff9384160261ffff60e01b191617600160e01b93909216929092021790556001600160a01b0390811660c05290811660a0521660805261076c600855600580546001600160801b0316600560831b17905562000195565b80516001600160a01b03811681146200010557600080fd5b919050565b805161ffff811681146200010557600080fd5b60008060008060008060c087890312156200013757600080fd5b6200014287620000ed565b95506200015260208801620000ed565b94506200016260408801620000ed565b935062000172606088016200010a565b925062000182608088016200010a565b915060a087015190509295509295509295565b60805160a05160c051614a996200032a600039600081816106c20152818161074f01528181610c4801528181610f78015281816112dd015281816113b9015281816115a0015281816119460152818161219e015281816123ba015281816125a401528181612d76015281816130fb0152818161319e015261329d0152600081816103a50152818161069d01528181610c0a01528181610f39015281816110760152818161139001528181611562015281816119f90152818161217d0152818161238d0152818161258301528181612d4901528181612fc3015281816130bd015281816131630152818161323e01528181613277015281816132d001526134310152600081816107280152818161081701528181610911015281816109ad01528181610b3001528181610cb201528181610ddd015281816111720152818161160a0152818161173501528181611a6601528181611d0f01528181611e4f01528181611e7801528181611f1501528181612a6801528181612b1901528181612ddc01528181613e730152613f180152614a996000f3fe608060405234801561001057600080fd5b50600436106102fd5760003560e01c806370a082311161019c578063aa6ca808116100ee578063d66bd52411610097578063dd62ed3e11610071578063dd62ed3e146107b4578063ddca3f43146107ed578063e9dcafaa1461080257600080fd5b8063d66bd52414610779578063d832b87a14610799578063da33b3df146107a157600080fd5b8063c45a0155116100c8578063c45a015514610723578063d21220a71461074a578063d5d7b44b1461077157600080fd5b8063aa6ca8081461068f578063b5093541146106ed578063ba81c3851461070057600080fd5b806395d89b4111610150578063a457c2d71161012a578063a457c2d714610656578063a66395e614610669578063a9059cbb1461067c57600080fd5b806395d89b41146106015780639860691c1461063a57806399b64de11461064357600080fd5b80638858c753116101815780638858c753146105b657806389afcb44146105bf5780638a689784146105e757600080fd5b806370a082311461056d57806377c6a7151461059657600080fd5b8063313ce56711610255578063597e1fb5116102095780636447c35d116101e35780636447c35d1461051557806364be513f146105285780636a6278421461055a57600080fd5b8063597e1fb5146104e257806362a6d197146104ef57806363f19ea11461050257600080fd5b80634617a9371161023a5780634617a937146104875780634e44c32e1461048f578063591f09eb146104b757600080fd5b8063313ce56714610465578063395093511461047457600080fd5b806311d14c6b116102b7578063268c74e411610291578063268c74e4146104175780632a635b4e14610420578063300c947a1461045257600080fd5b806311d14c6b146103df57806318160ddd146103f257806323b872dd1461040457600080fd5b806306fdde03116102e857806306fdde031461033b578063095ea7b31461037d5780630dfe1681146103a057600080fd5b8062113e0814610302578062a5359814610331575b600080fd5b600454604080516001600160701b038084168252600160701b9093049092166020830152015b60405180910390f35b610339610815565b005b60408051808201909152600c81527f5669727475737761702d4c50000000000000000000000000000000000000000060208201525b604051610328919061435c565b61039061038b366004614387565b6108f5565b6040519015158152602001610328565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610328565b6103396103ed3660046143b3565b61090f565b6002545b604051908152602001610328565b6103906104123660046143dc565b610ac8565b6103f660075481565b61043361042e366004614466565b610aec565b604080516001600160a01b039093168352602083019190915201610328565b6103f66104603660046144e2565b6114d6565b60405160128152602001610328565b610390610482366004614387565b611c55565b6103f6611c94565b6004546104a490600160f01b900461ffff1681565b60405161ffff9091168152602001610328565b6005546104ca906001600160801b031681565b6040516001600160801b039091168152602001610328565b600b546103909060ff1681565b6103c76104fd366004614555565b611ce3565b610339610510366004614555565b611d0d565b6103396105233660046145df565b611e44565b60045461054290600160701b90046001600160701b031681565b6040516001600160701b039091168152602001610328565b6103f6610568366004614685565b61232e565b6103f661057b366004614685565b6001600160a01b031660009081526020819052604090205490565b6103f66105a4366004614685565b600c6020526000908152604090205481565b6103f660085481565b6105d26105cd366004614685565b612576565b60408051928352602083019190915201610328565b6005546104ca90600160801b90046001600160801b031681565b60408051808201909152600781527f56535741504c50000000000000000000000000000000000000000000000000006020820152610370565b6103f660065481565b6103396106513660046146b2565b612832565b610390610664366004614387565b612933565b610339610677366004614555565b6129dd565b61039061068a366004614387565b612a50565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f000000000000000000000000000000000000000000000000000000000000000016602082015201610328565b6103396106fb3660046146eb565b612a5e565b61039061070e366004614685565b600a6020526000908152604090205460ff1681565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6103f661304e565b6103f6610787366004614685565b600d6020526000908152604090205481565b6009546103f6565b600454610542906001600160701b031681565b6103f66107c23660046146eb565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6004546104a490600160e01b900461ffff1681565b6103f66108103660046144e2565b613067565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108979190614724565b6001600160a01b0316336001600160a01b0316146108e15760405162461bcd60e51b81526020600482015260026024820152614f4560f01b60448201526064015b60405180910390fd5b600b805460ff19811660ff90911615179055565b6000336109038185856134f7565b60019150505b92915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109919190614724565b6001600160a01b0316336001600160a01b03161480610a4257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2d9190614724565b6001600160a01b0316336001600160a01b0316145b610a735760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b600580546001600160801b03908116600160801b918416918202179091556040519081527fcaaa7d3acc870fbbecd0fd5b1b5318711a76bc6beee2883e7c8d6bbf3c77b3ad906020015b60405180910390a150565b600033610ad685828561361b565b610ae18585856136ad565b506001949350505050565b600080610af7613880565b600b5460ff1615610b2e5760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fea77eae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb09190614724565b6001600160a01b0316336001600160a01b031614610bf55760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b6001600160a01b03861615801590610c3f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614155b8015610c7d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614155b610cae5760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d329190614724565b60405163a8c6edc960e01b81526001600160a01b038a81166004830152306024830152919091169063a8c6edc99060440161010060405180830381865afa158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da59190614741565b60408082015160a083015191516334a2a5c360e11b81526001600160a01b0391821660048201529181166024830152919250818a16917f000000000000000000000000000000000000000000000000000000000000000016906369454b8690604401602060405180830381865afa158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e489190614724565b6001600160a01b031614610e875760405162461bcd60e51b81526004016108d890602080825260049082015263049494b560e41b604082015260600190565b80608001518911158015610eb557506040808201516001600160a01b03166000908152600d60205220548911155b610ee75760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b6040808201516001600160a01b03166000908152600a602052205460ff16610f375760405162461bcd60e51b8152602060048201526003602482015262544e5760e81b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480610fb057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b610fe25760405162461bcd60e51b815260206004820152600360248201526213939560ea1b60448201526064016108d8565b610ff18160400151888b6138d9565b60006110068a83608001518460600151613930565b90508415611072576020820151604080840151905163cc1fd73160e01b8152339263cc1fd7319261103f9286908c908c906004016147e1565b600060405180830381600087803b15801561105957600080fd5b505af115801561106d573d6000803e3d6000fd5b505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683602001516001600160a01b0316146110c957600454600160701b90046001600160701b03166110d6565b6004546001600160701b03165b6001600160701b03166110ec84602001516139fa565b6110f6919061484b565b90508181101561112e5760405162461bcd60e51b815260206004820152600360248201526212509160ea1b60448201526064016108d8565b61115661113b838361484b565b60646111478b8561485e565b611151919061488b565b613ae7565b6020840151955093508315611170576111708533866138d9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f29190614724565b6001600160a01b031663de9ea2398b308785886060015161121391906148ad565b61121d919061484b565b8f886080015161122d919061484b565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526064820152608401600060405180830381600087803b15801561128157600080fd5b505af1158015611295573d6000803e3d6000fd5b505050505060006112a983604001516139fa565b905060008082116112bb5760006112ce565b6112ce8285608001518660600151613930565b905060008111801561131557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684602001516001600160a01b0316145b1561133e5760045461133b9082906001600160701b03600160701b820481169116613930565b90505b600680548201808255604080870180516001600160a01b039081166000908152600c60209081528482205490950390955581518116855282852095909555519093168252600d905220556113e26113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b6113dd7f00000000000000000000000000000000000000000000000000000000000000006139fa565b613aff565b6040808301516001600160a01b0381166000908152600d60205291909120547f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e919061142c611c94565b604080516001600160a01b03909416845260208401929092529082015260600160405180910390a160208083015160408085015181516001600160a01b039384168152908316938101939093528201839052606082018c90528a8116608083015289169033907f84e4b114d7cc75c5991508169b879228cf0ae428ba30144d51b8fc6a674aa9a89060a00160405180910390a350506114cb6001600355565b965096945050505050565b60006114e0613880565b600b5460ff16156115175760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6000861161154d5760405162461bcd60e51b815260206004820152600360248201526249414f60e81b60448201526064016108d8565b6001600160a01b0384161580159061159757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b80156115d557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b6116065760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168a9190614724565b60405163a8c6edc960e01b81523060048201526001600160a01b038881166024830152919091169063a8c6edc99060440161010060405180830381865afa1580156116d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fd9190614741565b602081015160a08201516040516334a2a5c360e11b81526001600160a01b0392831660048201529082166024820152919250808816917f0000000000000000000000000000000000000000000000000000000000000000909116906369454b8690604401602060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190614724565b6001600160a01b0316146117e15760405162461bcd60e51b81526004016108d890602080825260049082015263049494b560e41b604082015260600190565b8060800151871061181a5760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b60608101516080820151600454600092611840928b92600160f01b900461ffff16613b99565b90506118518260400151878a6138d9565b83156118bb576020820151604080840151905163cc1fd73160e01b8152339263cc1fd731926118889286908b908b906004016147e1565b600060405180830381600087803b1580156118a257600080fd5b505af11580156118b6573d6000803e3d6000fd5b505050505b60006118ca83602001516139fa565b6020808501516001600160a01b03166000908152600d90915260409020549091506118f5908261484b565b93508184101561192d5760405162461bcd60e51b815260206004820152600360248201526249494160e81b60448201526064016108d8565b60006119428285606001518660800151613930565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684604001516001600160a01b0316036119a5576004546119a29082906001600160701b03600160701b820481169116613930565b90505b600680548201808255602080870180516001600160a01b039081166000908152600c845260408082205490950390955581518116855283852095909555519093168252600d90925220819055611a1d6113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b6000611a27611c94565b9050600754811115611a645760405162461bcd60e51b81526004016108d8906020808252600490820152631510941560e21b604082015260600190565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae69190614724565b6001600160a01b031663de9ea239308b888860600151611b0691906148ad565b8e8960800151611b16919061484b565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526064820152608401600060405180830381600087803b158015611b6a57600080fd5b505af1158015611b7e573d6000803e3d6000fd5b505050602080860151604080516001600160a01b0390921682529181018590529081018390527f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e915060600160405180910390a160208085015160408087015181516001600160a01b039384168152908316938101939093528201859052606082018c90528a8116608083015289169033907f84e4b114d7cc75c5991508169b879228cf0ae428ba30144d51b8fc6a674aa9a89060a0015b60405180910390a350505050611c4c6001600355565b95945050505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091906109039082908690611c8f9087906148ad565b6134f7565b6004546000906001600160701b031680611caf576000611cdd565b600181901b611cc16103e860646148c0565b62ffffff16600654611cd3919061485e565b611cdd919061488b565b91505090565b60098181548110611cf357600080fd5b6000918252602090912001546001600160a01b0316905081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8f9190614724565b6001600160a01b0316336001600160a01b031614611dd45760405162461bcd60e51b81526020600482015260026024820152614f4560f01b60448201526064016108d8565b600754811115611e0f5760405162461bcd60e51b81526004016108d890602080825260049082015263125495d560e21b604082015260600190565b60088190556040518181527f77f0773cce90b3c7a365117b2463a279ec138c4ab7a241d604f91ebabd8fc25690602001610abd565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611f0d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ed4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef89190614724565b6001600160a01b0316336001600160a01b0316145b80611faa57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f959190614724565b6001600160a01b0316336001600160a01b0316145b611fdb5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b60015b81518110156120a05781611ff360018361484b565b81518110612003576120036148e7565b60200260200101516001600160a01b0316828281518110612026576120266148e7565b60200260200101516001600160a01b0316116120905760405162461bcd60e51b8152602060048201526024808201527f616c6c6f77206c697374206d75737420626520756e6971756520616e6420736f6044820152631c9d195960e21b60648201526084016108d8565b612099816148fd565b9050611fde565b50600060098054806020026020016040519081016040528092919081815260200182805480156120f957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120db575b5050505050905060005b8151811015612166576000600a6000848481518110612124576121246148e7565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905561215f816148fd565b9050612103565b50815161217a90600990602085019061427a565b507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006000805b85518110156122e957836001600160a01b03168682815181106121e6576121e66148e7565b60200260200101516001600160a01b0316141580156122305750826001600160a01b031686828151811061221c5761221c6148e7565b60200260200101516001600160a01b031614155b156122d9576001600a600088848151811061224d5761224d6148e7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c60008783815181106122a2576122a26148e7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054826122d691906148ad565b91505b6122e2816148fd565b90506121c1565b5060068190556040517fc2d08e7ae40f88bd169469bbcfa69c8213cb98772e0bab7de792256c59139eec9061231f908790614916565b60405180910390a15050505050565b6000612338613880565b600b5460ff161561236f5760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6004546001600160701b0380821691600160701b90041660006123b17f00000000000000000000000000000000000000000000000000000000000000006139fa565b905060006123de7f00000000000000000000000000000000000000000000000000000000000000006139fa565b905060006123ec858461484b565b905060006123fa858461484b565b9050600061240760025490565b905080600003612444576103e8612426612421848661485e565b613bee565b612430919061484b565b975061243f60006103e8613cd6565b61246a565b61246787612452838661485e565b61245c919061488b565b87611147848661485e565b97505b6000612474611c94565b9050806124846103e860646148c0565b62ffffff1661249391906148ad565b6124a06103e860646148c0565b6124af9062ffffff168b61485e565b6124b9919061488b565b9850600089116124f15760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b60448201526064016108d8565b6124fb8a8a613cd6565b6125058686613aff565b896001600160a01b03167f94c792774c59479f7bd68442f3af3691c02123a5aabee8b6f9116d8af8aa666985858c61253c60025490565b60408051948552602085019390935291830152606082015260800160405180910390a250505050505050506125716001600355565b919050565b600080612581613880565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060006125ce836139fa565b905060006125db836139fa565b905060006125e8306139fa565b905060006125f560025490565b905080612602838661485e565b61260c919061488b565b975080612619838561485e565b612623919061488b565b96506000881180156126355750600087115b6126675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b60448201526064016108d8565b6126713083613d3f565b61267c868a8a6138d9565b612687858a896138d9565b6000612691611c94565b905080156127a75760005b6009548110156127a5576000600982815481106126bb576126bb6148e7565b60009182526020808320909101546001600160a01b0316808352600d9091526040909120549091508015612792576000856126f6888461485e565b612700919061488b565b905061270d838f836138d9565b6001600160a01b0383166000908152600c602052604090205486612731898361485e565b61273b919061488b565b612745908261484b565b6001600160a01b0385166000908152600c60205260409020819055600680549091018290039055612776828461484b565b6001600160a01b0385166000908152600d602052604090205550505b50508061279e906148fd565b905061269c565b505b6127b0876139fa565b94506127bb866139fa565b93506127c78585613aff565b6001600160a01b038a16337fa476cebfbe7485684f5578d84d8a64a8afe93a0a2a3047bd6f3e681e108b8f118b8b6127fe60025490565b6040805193845260208401929092529082015260600160405180910390a35050505050505061282d6001600355565b915091565b61283a613e71565b60008261ffff16118015612852575060008161ffff16115b801561286357506103e88261ffff16105b801561287457506103e88161ffff16105b6128a65760405162461bcd60e51b815260206004820152600360248201526249464360e81b60448201526064016108d8565b600480546001600160e01b0316600160e01b61ffff8581169182027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217600160f01b928516928302179092556040805192835260208301919091527faa1ebd1f8841401ae5e1a0f2febc87d5f597ae458fca8277cd0e43b92633183c91015b60405180910390a15050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156129d05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016108d8565b610ae182868684036134f7565b6129e5613e71565b60008111612a1b5760405162461bcd60e51b815260206004820152600360248201526212549560ea1b60448201526064016108d8565b60078190556040518181527f047f24f47d2c93ef7523cb3c84c3b367df61e4899214a2a48784cfa09da91fdf90602001610abd565b6000336109038185856136ad565b612a66613880565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ac4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae89190614724565b6001600160a01b0316336001600160a01b0316148015612b115750600854612b0e611c94565b10155b80612bae57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b999190614724565b6001600160a01b0316336001600160a01b0316145b612bdf5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b6001600160a01b0382166000908152600a602052604090205460ff16612c2d5760405162461bcd60e51b8152602060048201526003602482015262544e5760e81b60448201526064016108d8565b600080826001600160a01b031663aa6ca8086040518163ffffffff1660e01b81526004016040805180830381865afa158015612c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c919190614963565b91509150600080846001600160a01b031662113e086040518163ffffffff1660e01b81526004016040805180830381865afa158015612cd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf891906149a9565b6001600160701b031691506001600160701b03169150856001600160a01b0316846001600160a01b031614612d2c57919291905b6001600160a01b038681166000908152600d6020526040902054907f000000000000000000000000000000000000000000000000000000000000000081169085161480612daa57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b8015612e5457506040516334a2a5c360e11b81526001600160a01b0388811660048301528581166024830152808816917f0000000000000000000000000000000000000000000000000000000000000000909116906369454b8690604401602060405180830381865afa158015612e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e499190614724565b6001600160a01b0316145b612e865760405162461bcd60e51b81526020600482015260036024820152620494e560ec1b60448201526064016108d8565b6001600160a01b0387166000908152600c60209081526040808320805460068054919091039055839055600d909152812055612ec38787836138d9565b856001600160a01b031663e9dcafaa612f438386868b6001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3a91906149dc565b61ffff16613f6d565b604080516000815260208101918290526001600160e01b031960e085901b16909152612f77919088903090602481016149f9565b6020604051808303816000875af1158015612f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fba9190614a35565b50612fe76113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b7f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e876000613013611c94565b604080516001600160a01b03909416845260208401929092529082015260600160405180910390a1505050505061304a6001600355565b5050565b600061305d6103e860646148c0565b62ffffff16905090565b6000613071613880565b600b5460ff16156130a85760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6001600160a01b038416158015906130f257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b801561313057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b6131615760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b031614806131d257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b6132045760405162461bcd60e51b815260206004820152600360248201526213939560ea1b60448201526064016108d8565b6000861161323a5760405162461bcd60e51b815260206004820152600360248201526249414f60e81b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b03161461329b577f00000000000000000000000000000000000000000000000000000000000000006132bd565b7f00000000000000000000000000000000000000000000000000000000000000005b60045490915060009081906133099084907f0000000000000000000000000000000000000000000000000000000000000000906001600160701b0380821691600160701b900416613fbb565b915091508089106133425760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b61334d88888b6138d9565b600061336f8a84846004601c9054906101000a900461ffff1661ffff16613b99565b905085156133d55760405163cc1fd73160e01b8152339063cc1fd731906133a29087908d9086908d908d906004016147e1565b600060405180830381600087803b1580156133bc57600080fd5b505af11580156133d0573d6000803e3d6000fd5b505050505b826133df856139fa565b6133e9919061484b565b94506000851180156133fb5750808510155b61342d5760405162461bcd60e51b815260206004820152600360248201526249494160e81b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b03161490506134a08161347d576134788c8561484b565b613487565b61348787866148ad565b82613496576113dd88876148ad565b6113dd8d8661484b565b50604080516001600160a01b0386811682528b81166020830152918101839052606081018c90529089169033907f54787c404bb33c88e86f4baf88183a3b0141d0a848e6a9f7a13b66ae3a9b73d190608001611c36565b6001600160a01b0383166135595760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016108d8565b6001600160a01b0382166135ba5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016108d8565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146136a7578181101561369a5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108d8565b6136a784848484036134f7565b50505050565b6001600160a01b0383166137295760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016108d8565b6001600160a01b03821661378b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016108d8565b6001600160a01b0383166000908152602081905260409020548181101561381a5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016108d8565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36136a7565b6002600354036138d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d8565b6002600355565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261392b908490613fee565b505050565b60008084116139815760405162461bcd60e51b815260206004820152601a60248201527f56535741503a20494e53554646494349454e545f414d4f554e5400000000000060448201526064016108d8565b6000831180156139915750600082115b6139dd5760405162461bcd60e51b815260206004820152601d60248201527f56535741503a20494e53554646494349454e545f4c495155494449545900000060448201526064016108d8565b826139e8838661485e565b6139f2919061488b565b949350505050565b604051306024820152600090819081906001600160a01b0385169060440160408051601f198184030181529181526020820180516001600160e01b03166370a0823160e01b17905251613a4d9190614a4e565b600060405180830381855afa9150503d8060008114613a88576040519150601f19603f3d011682016040523d82523d6000602084013e613a8d565b606091505b5091509150818015613aa157506020815110155b613ad35760405162461bcd60e51b815260206004820152600360248201526223212360e91b60448201526064016108d8565b808060200190518101906139f29190614a35565b6000818310613af65781613af8565b825b9392505050565b600580546fffffffffffffffffffffffffffffffff1916436001600160801b0316179055600480546001600160e01b031916600160701b6001600160701b038481169182026dffffffffffffffffffffffffffff1916929092179185169182179092556040805191825260208201929092527fa74621c1abba1dca03b6708d02443d60ddfd3f4273745060c4355afc9daa52c69101612927565b6000806103e8613ba9878761485e565b613bb3919061485e565b9050600083613bc2888761484b565b613bcc919061485e565b9050613bd8818361488b565b613be39060016148ad565b979650505050505050565b600081600003613c0057506000919050565b60006001613c0d846140d3565b901c6001901b90506001818481613c2657613c26614875565b048201901c90506001818481613c3e57613c3e614875565b048201901c90506001818481613c5657613c56614875565b048201901c90506001818481613c6e57613c6e614875565b048201901c90506001818481613c8657613c86614875565b048201901c90506001818481613c9e57613c9e614875565b048201901c90506001818481613cb657613cb6614875565b048201901c9050613af881828581613cd057613cd0614875565b04613ae7565b8060026000828254613ce891906148ad565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038216613d9f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016108d8565b6001600160a01b03821660009081526020819052604090205481811015613e135760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016108d8565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef39190614724565b6001600160a01b0316336001600160a01b03161480613f3a5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b613f6b5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b565b600080613f7a838761485e565b90506000613f88858361485e565b9050600082613f996103e88961485e565b613fa391906148ad565b9050613faf818361488b565b98975050505050505050565b600080856001600160a01b0316856001600160a01b031614613fde578284613fe1565b83835b9097909650945050505050565b6000614043826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166141679092919063ffffffff16565b80519091501561392b57808060200190518101906140619190614a6a565b61392b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108d8565b600080608083901c156140e857608092831c92015b604083901c156140fa57604092831c92015b602083901c1561410c57602092831c92015b601083901c1561411e57601092831c92015b600883901c1561413057600892831c92015b600483901c1561414257600492831c92015b600283901c1561415457600292831c92015b600183901c156109095760010192915050565b60606139f2848460008585600080866001600160a01b0316858760405161418e9190614a4e565b60006040518083038185875af1925050503d80600081146141cb576040519150601f19603f3d011682016040523d82523d6000602084013e6141d0565b606091505b5091509150613be3878383876060831561424b578251600003614244576001600160a01b0385163b6142445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108d8565b50816139f2565b6139f283838151156142605781518083602001fd5b8060405162461bcd60e51b81526004016108d8919061435c565b8280548282559060005260206000209081019282156142e7579160200282015b828111156142e757825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0390911617825560209092019160019091019061429a565b506142f39291506142f7565b5090565b5b808211156142f357600081556001016142f8565b60005b8381101561432757818101518382015260200161430f565b50506000910152565b6000815180845261434881602086016020860161430c565b601f01601f19169290920160200192915050565b602081526000613af86020830184614330565b6001600160a01b038116811461438457600080fd5b50565b6000806040838503121561439a57600080fd5b82356143a58161436f565b946020939093013593505050565b6000602082840312156143c557600080fd5b81356001600160801b0381168114613af857600080fd5b6000806000606084860312156143f157600080fd5b83356143fc8161436f565b9250602084013561440c8161436f565b929592945050506040919091013590565b60008083601f84011261442f57600080fd5b50813567ffffffffffffffff81111561444757600080fd5b60208301915083602082850101111561445f57600080fd5b9250929050565b60008060008060008060a0878903121561447f57600080fd5b8635955060208701356144918161436f565b945060408701356144a18161436f565b935060608701359250608087013567ffffffffffffffff8111156144c457600080fd5b6144d089828a0161441d565b979a9699509497509295939492505050565b6000806000806000608086880312156144fa57600080fd5b85359450602086013561450c8161436f565b9350604086013561451c8161436f565b9250606086013567ffffffffffffffff81111561453857600080fd5b6145448882890161441d565b969995985093965092949392505050565b60006020828403121561456757600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156145a8576145a861456e565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156145d7576145d761456e565b604052919050565b600060208083850312156145f257600080fd5b823567ffffffffffffffff8082111561460a57600080fd5b818501915085601f83011261461e57600080fd5b8135818111156146305761463061456e565b8060051b91506146418483016145ae565b818152918301840191848101908884111561465b57600080fd5b938501935b83851015613faf57843592506146758361436f565b8282529385019390850190614660565b60006020828403121561469757600080fd5b8135613af88161436f565b61ffff8116811461438457600080fd5b600080604083850312156146c557600080fd5b82356146d0816146a2565b915060208301356146e0816146a2565b809150509250929050565b600080604083850312156146fe57600080fd5b82356147098161436f565b915060208301356146e08161436f565b80516125718161436f565b60006020828403121561473657600080fd5b8151613af88161436f565b6000610100828403121561475457600080fd5b61475c614584565b825162ffffff8116811461476f57600080fd5b815261477d60208401614719565b602082015261478e60408401614719565b604082015260608301516060820152608083015160808201526147b360a08401614719565b60a08201526147c460c08401614719565b60c08201526147d560e08401614719565b60e08201529392505050565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561090957610909614835565b808202811582820484141761090957610909614835565b634e487b7160e01b600052601260045260246000fd5b6000826148a857634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561090957610909614835565b62ffffff8181168382160280821691908281146148df576148df614835565b505092915050565b634e487b7160e01b600052603260045260246000fd5b60006001820161490f5761490f614835565b5060010190565b6020808252825182820181905260009190848201906040850190845b818110156149575783516001600160a01b031683529284019291840191600101614932565b50909695505050505050565b6000806040838503121561497657600080fd5b82516149818161436f565b60208401519092506146e08161436f565b80516001600160701b038116811461257157600080fd5b600080604083850312156149bc57600080fd5b6149c583614992565b91506149d360208401614992565b90509250929050565b6000602082840312156149ee57600080fd5b8151613af8816146a2565b84815260006001600160a01b03808616602084015280851660408401525060806060830152614a2b6080830184614330565b9695505050505050565b600060208284031215614a4757600080fd5b5051919050565b60008251614a6081846020870161430c565b9190910192915050565b600060208284031215614a7c57600080fd5b81518015158114613af857600080fdfea164736f6c6343000812000aa164736f6c6343000812000a
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200014f5760003560e01c80636d495f8311620000c0578063b5358fab116200008b578063c9c65396116200006e578063c9c65396146200034e578063f851a4401462000365578063fea77eae146200037957600080fd5b8063b5358fab1462000323578063c4ce80d1146200033757600080fd5b80636d495f8314620002ca57806370905dce14620002e15780638d018b4d14620002f5578063ad4d1ee5146200030c57600080fd5b806337e0376b116200011e578063574f2ba31162000101578063574f2ba3146200027a5780635e278915146200028c57806369454b86146200029657600080fd5b806337e0376b146200024f5780634dd18bf5146200026357600080fd5b80630d19c79d14620001545780630e18b68114620001ff5780631e3dd18b146200020b57806326782247146200023b575b600080fd5b600954600a54600b54600c54620001b5936001600160a01b03908116938116929081169161ffff7401000000000000000000000000000000000000000083048116927601000000000000000000000000000000000000000000009004169086565b604080516001600160a01b0397881681529587166020870152939095169284019290925261ffff908116606084015216608082015260a081019190915260c0015b60405180910390f35b620002096200038d565b005b620002226200021c36600462000f96565b62000432565b6040516001600160a01b039091168152602001620001f6565b60035462000222906001600160a01b031681565b60075462000222906001600160a01b031681565b620002096200027436600462000fc9565b6200045d565b600154604051908152602001620001f6565b62000209620004f3565b62000222620002a736600462000ff0565b60006020818152928152604080822090935290815220546001600160a01b031681565b62000209620002db36600462000fc9565b6200058f565b60045462000222906001600160a01b031681565b62000209620003063660046200102e565b62000727565b620002096200031d36600462000fc9565b620008bc565b60055462000222906001600160a01b031681565b620002096200034836600462000fc9565b6200094d565b620002226200035f36600462000ff0565b62000acb565b60025462000222906001600160a01b031681565b60065462000222906001600160a01b031681565b6003546001600160a01b03163314620003d35760405162461bcd60e51b81526020600482015260036024820152624f504160e81b60448201526064015b60405180910390fd5b60038054600280546001600160a01b0383166001600160a01b031991821681179092559091169091556040519081527f49979123b2bc91263f3f2f1a87e92ce0e486c6c70943d1d67f8beee550efb663906020015b60405180910390a1565b600181815481106200044357600080fd5b6000918252602090912001546001600160a01b0316905081565b6002546001600160a01b031633146200049e5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f07a0003b2bc46a6950059c8ae85d2c7e50e9b46f922fe6aba4317d26f2f6f0f9906020015b60405180910390a150565b6005546001600160a01b03163314620005355760405162461bcd60e51b81526020600482015260036024820152624f504160e81b6044820152606401620003ca565b60058054600480546001600160a01b0383166001600160a01b031991821681179092559091169091556040519081527f4e08187fea80af9168fe976bfc7234414071130284ac83e2a6563750f74a2cf39060200162000428565b6002546001600160a01b03163314620005d05760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b6001600160a01b038116620006285760405162461bcd60e51b815260206004820152600560248201527f4956504d410000000000000000000000000000000000000000000000000000006044820152606401620003ca565b306001600160a01b0316816001600160a01b031663e14f870d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000671573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006979190620010a8565b6001600160a01b031614620006d85760405162461bcd60e51b8152600401620003ca906020808252600490820152634956504d60e01b604082015260600190565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fe823a8e80e62dc26cf857355ee4f23825d6881b26707a1a9a9b3248ac3af0aec90602001620004e8565b6002546001600160a01b03163314620007685760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b62ffffff811115620007a35760405162461bcd60e51b815260206004820152600360248201526210551360ea1b6044820152606401620003ca565b60015b818110156200086d578282620007be600184620010de565b818110620007d057620007d0620010f4565b9050602002016020810190620007e7919062000fc9565b6001600160a01b0316838383818110620008055762000805620010f4565b90506020020160208101906200081c919062000fc9565b6001600160a01b0316116200085a5760405162461bcd60e51b8152602060048201526003602482015262414c5560e81b6044820152606401620003ca565b62000865816200110a565b9050620007a6565b506200087c6008838362000f09565b507f3100a95101e6b59aeaea5117410f1539971c1536f72dc73ce806a450c85e394c8282604051620008b092919062001126565b60405180910390a15050565b6004546001600160a01b03163314620008fe5760405162461bcd60e51b81526020600482015260036024820152624f454160e81b6044820152606401620003ca565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527fe193ea528cfd9222d51ca7a5197c2f22df949ae773d1069cfabeffa68fe856bd90602001620004e8565b6002546001600160a01b031633146200098e5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b6044820152606401620003ca565b6001600160a01b038116620009cf5760405162461bcd60e51b8152600401620003ca906020808252600490820152634945524160e01b604082015260600190565b306001600160a01b0316816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a18573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a3e9190620010a8565b6001600160a01b03161462000a7c5760405162461bcd60e51b815260206004820152600360248201526224a2a960e91b6044820152606401620003ca565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f565432aa4b07668ec2d26adccb36e35bebdd6779cc94dca1f3b704e253b4010590602001620004e8565b6000816001600160a01b0316836001600160a01b03160362000b155760405162461bcd60e51b8152602060048201526002602482015261494160f01b6044820152606401620003ca565b60008062000b24858562000e87565b90925090506001600160a01b03821662000b665760405162461bcd60e51b81526020600482015260026024820152615a4160f01b6044820152606401620003ca565b6001600160a01b038281166000908152602081815260408083208585168452909152902054161562000bc05760405162461bcd60e51b8152602060048201526002602482015261504560f01b6044820152606401620003ca565b6040805160c081018252308082526001600160a01b03858116602084018190529085169383018490526103e56060840181905260808401526107d060a0909301839052600980546001600160a01b03199081169093179055600a8054909216179055600b80547fffffffffffffffffffff00000000000000000000000000000000000000000000169092177503e50000000000000000000000000000000000000000177fffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffff167703e50000000000000000000000000000000000000000000017909155600c55600062000cb3838362000eba565b90508060405162000cc49062000f71565b8190604051809103906000f590508015801562000ce5573d6000803e3d6000fd5b50600980546001600160a01b0319908116909155600a80549091169055600b80547fffffffffffffffff0000000000000000000000000000000000000000000000001690556000600c55604051636447c35d60e01b81529094506001600160a01b03851690636447c35d9062000d619060089060040162001178565b600060405180830381600087803b15801562000d7c57600080fd5b505af115801562000d91573d6000803e3d6000fd5b505050506001600160a01b0383811660008181526020818152604080832087861680855290835281842080546001600160a01b0319908116978c169788179091558484528285208686528452828520805482168817905560018054808201825595527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6909401805490941686179093558051948552309185019190915283019190915260608201526103e56080820181905260a08201526107d060c08201527f70084adbff44be952e8bb87558f46235532635d476e79e29558665fa7d6c12ce9060e00160405180910390a15050505b92915050565b600080826001600160a01b0316846001600160a01b03161062000eac57828462000eaf565b83835b915091509250929050565b600080600062000ecb858562000e87565b604080516001600160a01b03938416602080830191909152929093168382015280518084038201815260609093019052815191012095945050505050565b82805482825590600052602060002090810192821562000f5f579160200282015b8281111562000f5f5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019062000f2a565b5062000f6d92915062000f7f565b5090565b614dc380620011cb83390190565b5b8082111562000f6d576000815560010162000f80565b60006020828403121562000fa957600080fd5b5035919050565b6001600160a01b038116811462000fc657600080fd5b50565b60006020828403121562000fdc57600080fd5b813562000fe98162000fb0565b9392505050565b600080604083850312156200100457600080fd5b8235620010118162000fb0565b91506020830135620010238162000fb0565b809150509250929050565b600080602083850312156200104257600080fd5b823567ffffffffffffffff808211156200105b57600080fd5b818501915085601f8301126200107057600080fd5b8135818111156200108057600080fd5b8660208260051b85010111156200109657600080fd5b60209290920196919550909350505050565b600060208284031215620010bb57600080fd5b815162000fe98162000fb0565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000e815762000e81620010c8565b634e487b7160e01b600052603260045260246000fd5b6000600182016200111f576200111f620010c8565b5060010190565b60208082528181018390526000908460408401835b868110156200116d578235620011518162000fb0565b6001600160a01b0316825291830191908301906001016200113b565b509695505050505050565b6020808252825482820181905260008481528281209092916040850190845b81811015620011be5783546001600160a01b03168352600193840193928501920162001197565b5090969550505050505056fe60e06040523480156200001157600080fd5b506001600381905550336001600160a01b0316630d19c79d6040518163ffffffff1660e01b815260040160c060405180830381865afa15801562000059573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200007f91906200011d565b600755600480546001600160e01b0316600160f01b61ffff9384160261ffff60e01b191617600160e01b93909216929092021790556001600160a01b0390811660c05290811660a0521660805261076c600855600580546001600160801b0316600560831b17905562000195565b80516001600160a01b03811681146200010557600080fd5b919050565b805161ffff811681146200010557600080fd5b60008060008060008060c087890312156200013757600080fd5b6200014287620000ed565b95506200015260208801620000ed565b94506200016260408801620000ed565b935062000172606088016200010a565b925062000182608088016200010a565b915060a087015190509295509295509295565b60805160a05160c051614a996200032a600039600081816106c20152818161074f01528181610c4801528181610f78015281816112dd015281816113b9015281816115a0015281816119460152818161219e015281816123ba015281816125a401528181612d76015281816130fb0152818161319e015261329d0152600081816103a50152818161069d01528181610c0a01528181610f39015281816110760152818161139001528181611562015281816119f90152818161217d0152818161238d0152818161258301528181612d4901528181612fc3015281816130bd015281816131630152818161323e01528181613277015281816132d001526134310152600081816107280152818161081701528181610911015281816109ad01528181610b3001528181610cb201528181610ddd015281816111720152818161160a0152818161173501528181611a6601528181611d0f01528181611e4f01528181611e7801528181611f1501528181612a6801528181612b1901528181612ddc01528181613e730152613f180152614a996000f3fe608060405234801561001057600080fd5b50600436106102fd5760003560e01c806370a082311161019c578063aa6ca808116100ee578063d66bd52411610097578063dd62ed3e11610071578063dd62ed3e146107b4578063ddca3f43146107ed578063e9dcafaa1461080257600080fd5b8063d66bd52414610779578063d832b87a14610799578063da33b3df146107a157600080fd5b8063c45a0155116100c8578063c45a015514610723578063d21220a71461074a578063d5d7b44b1461077157600080fd5b8063aa6ca8081461068f578063b5093541146106ed578063ba81c3851461070057600080fd5b806395d89b4111610150578063a457c2d71161012a578063a457c2d714610656578063a66395e614610669578063a9059cbb1461067c57600080fd5b806395d89b41146106015780639860691c1461063a57806399b64de11461064357600080fd5b80638858c753116101815780638858c753146105b657806389afcb44146105bf5780638a689784146105e757600080fd5b806370a082311461056d57806377c6a7151461059657600080fd5b8063313ce56711610255578063597e1fb5116102095780636447c35d116101e35780636447c35d1461051557806364be513f146105285780636a6278421461055a57600080fd5b8063597e1fb5146104e257806362a6d197146104ef57806363f19ea11461050257600080fd5b80634617a9371161023a5780634617a937146104875780634e44c32e1461048f578063591f09eb146104b757600080fd5b8063313ce56714610465578063395093511461047457600080fd5b806311d14c6b116102b7578063268c74e411610291578063268c74e4146104175780632a635b4e14610420578063300c947a1461045257600080fd5b806311d14c6b146103df57806318160ddd146103f257806323b872dd1461040457600080fd5b806306fdde03116102e857806306fdde031461033b578063095ea7b31461037d5780630dfe1681146103a057600080fd5b8062113e0814610302578062a5359814610331575b600080fd5b600454604080516001600160701b038084168252600160701b9093049092166020830152015b60405180910390f35b610339610815565b005b60408051808201909152600c81527f5669727475737761702d4c50000000000000000000000000000000000000000060208201525b604051610328919061435c565b61039061038b366004614387565b6108f5565b6040519015158152602001610328565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610328565b6103396103ed3660046143b3565b61090f565b6002545b604051908152602001610328565b6103906104123660046143dc565b610ac8565b6103f660075481565b61043361042e366004614466565b610aec565b604080516001600160a01b039093168352602083019190915201610328565b6103f66104603660046144e2565b6114d6565b60405160128152602001610328565b610390610482366004614387565b611c55565b6103f6611c94565b6004546104a490600160f01b900461ffff1681565b60405161ffff9091168152602001610328565b6005546104ca906001600160801b031681565b6040516001600160801b039091168152602001610328565b600b546103909060ff1681565b6103c76104fd366004614555565b611ce3565b610339610510366004614555565b611d0d565b6103396105233660046145df565b611e44565b60045461054290600160701b90046001600160701b031681565b6040516001600160701b039091168152602001610328565b6103f6610568366004614685565b61232e565b6103f661057b366004614685565b6001600160a01b031660009081526020819052604090205490565b6103f66105a4366004614685565b600c6020526000908152604090205481565b6103f660085481565b6105d26105cd366004614685565b612576565b60408051928352602083019190915201610328565b6005546104ca90600160801b90046001600160801b031681565b60408051808201909152600781527f56535741504c50000000000000000000000000000000000000000000000000006020820152610370565b6103f660065481565b6103396106513660046146b2565b612832565b610390610664366004614387565b612933565b610339610677366004614555565b6129dd565b61039061068a366004614387565b612a50565b604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f000000000000000000000000000000000000000000000000000000000000000016602082015201610328565b6103396106fb3660046146eb565b612a5e565b61039061070e366004614685565b600a6020526000908152604090205460ff1681565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6103c77f000000000000000000000000000000000000000000000000000000000000000081565b6103f661304e565b6103f6610787366004614685565b600d6020526000908152604090205481565b6009546103f6565b600454610542906001600160701b031681565b6103f66107c23660046146eb565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6004546104a490600160e01b900461ffff1681565b6103f66108103660046144e2565b613067565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610873573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108979190614724565b6001600160a01b0316336001600160a01b0316146108e15760405162461bcd60e51b81526020600482015260026024820152614f4560f01b60448201526064015b60405180910390fd5b600b805460ff19811660ff90911615179055565b6000336109038185856134f7565b60019150505b92915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109919190614724565b6001600160a01b0316336001600160a01b03161480610a4257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2d9190614724565b6001600160a01b0316336001600160a01b0316145b610a735760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b600580546001600160801b03908116600160801b918416918202179091556040519081527fcaaa7d3acc870fbbecd0fd5b1b5318711a76bc6beee2883e7c8d6bbf3c77b3ad906020015b60405180910390a150565b600033610ad685828561361b565b610ae18585856136ad565b506001949350505050565b600080610af7613880565b600b5460ff1615610b2e5760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fea77eae6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb09190614724565b6001600160a01b0316336001600160a01b031614610bf55760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b6001600160a01b03861615801590610c3f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614155b8015610c7d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614155b610cae5760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d329190614724565b60405163a8c6edc960e01b81526001600160a01b038a81166004830152306024830152919091169063a8c6edc99060440161010060405180830381865afa158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da59190614741565b60408082015160a083015191516334a2a5c360e11b81526001600160a01b0391821660048201529181166024830152919250818a16917f000000000000000000000000000000000000000000000000000000000000000016906369454b8690604401602060405180830381865afa158015610e24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e489190614724565b6001600160a01b031614610e875760405162461bcd60e51b81526004016108d890602080825260049082015263049494b560e41b604082015260600190565b80608001518911158015610eb557506040808201516001600160a01b03166000908152600d60205220548911155b610ee75760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b6040808201516001600160a01b03166000908152600a602052205460ff16610f375760405162461bcd60e51b8152602060048201526003602482015262544e5760e81b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b03161480610fb057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681602001516001600160a01b0316145b610fe25760405162461bcd60e51b815260206004820152600360248201526213939560ea1b60448201526064016108d8565b610ff18160400151888b6138d9565b60006110068a83608001518460600151613930565b90508415611072576020820151604080840151905163cc1fd73160e01b8152339263cc1fd7319261103f9286908c908c906004016147e1565b600060405180830381600087803b15801561105957600080fd5b505af115801561106d573d6000803e3d6000fd5b505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683602001516001600160a01b0316146110c957600454600160701b90046001600160701b03166110d6565b6004546001600160701b03165b6001600160701b03166110ec84602001516139fa565b6110f6919061484b565b90508181101561112e5760405162461bcd60e51b815260206004820152600360248201526212509160ea1b60448201526064016108d8565b61115661113b838361484b565b60646111478b8561485e565b611151919061488b565b613ae7565b6020840151955093508315611170576111708533866138d9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f29190614724565b6001600160a01b031663de9ea2398b308785886060015161121391906148ad565b61121d919061484b565b8f886080015161122d919061484b565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526064820152608401600060405180830381600087803b15801561128157600080fd5b505af1158015611295573d6000803e3d6000fd5b505050505060006112a983604001516139fa565b905060008082116112bb5760006112ce565b6112ce8285608001518660600151613930565b905060008111801561131557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684602001516001600160a01b0316145b1561133e5760045461133b9082906001600160701b03600160701b820481169116613930565b90505b600680548201808255604080870180516001600160a01b039081166000908152600c60209081528482205490950390955581518116855282852095909555519093168252600d905220556113e26113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b6113dd7f00000000000000000000000000000000000000000000000000000000000000006139fa565b613aff565b6040808301516001600160a01b0381166000908152600d60205291909120547f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e919061142c611c94565b604080516001600160a01b03909416845260208401929092529082015260600160405180910390a160208083015160408085015181516001600160a01b039384168152908316938101939093528201839052606082018c90528a8116608083015289169033907f84e4b114d7cc75c5991508169b879228cf0ae428ba30144d51b8fc6a674aa9a89060a00160405180910390a350506114cb6001600355565b965096945050505050565b60006114e0613880565b600b5460ff16156115175760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6000861161154d5760405162461bcd60e51b815260206004820152600360248201526249414f60e81b60448201526064016108d8565b6001600160a01b0384161580159061159757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b80156115d557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b6116065760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168a9190614724565b60405163a8c6edc960e01b81523060048201526001600160a01b038881166024830152919091169063a8c6edc99060440161010060405180830381865afa1580156116d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fd9190614741565b602081015160a08201516040516334a2a5c360e11b81526001600160a01b0392831660048201529082166024820152919250808816917f0000000000000000000000000000000000000000000000000000000000000000909116906369454b8690604401602060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a29190614724565b6001600160a01b0316146117e15760405162461bcd60e51b81526004016108d890602080825260049082015263049494b560e41b604082015260600190565b8060800151871061181a5760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b60608101516080820151600454600092611840928b92600160f01b900461ffff16613b99565b90506118518260400151878a6138d9565b83156118bb576020820151604080840151905163cc1fd73160e01b8152339263cc1fd731926118889286908b908b906004016147e1565b600060405180830381600087803b1580156118a257600080fd5b505af11580156118b6573d6000803e3d6000fd5b505050505b60006118ca83602001516139fa565b6020808501516001600160a01b03166000908152600d90915260409020549091506118f5908261484b565b93508184101561192d5760405162461bcd60e51b815260206004820152600360248201526249494160e81b60448201526064016108d8565b60006119428285606001518660800151613930565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031684604001516001600160a01b0316036119a5576004546119a29082906001600160701b03600160701b820481169116613930565b90505b600680548201808255602080870180516001600160a01b039081166000908152600c845260408082205490950390955581518116855283852095909555519093168252600d90925220819055611a1d6113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b6000611a27611c94565b9050600754811115611a645760405162461bcd60e51b81526004016108d8906020808252600490820152631510941560e21b604082015260600190565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166337e0376b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae69190614724565b6001600160a01b031663de9ea239308b888860600151611b0691906148ad565b8e8960800151611b16919061484b565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526064820152608401600060405180830381600087803b158015611b6a57600080fd5b505af1158015611b7e573d6000803e3d6000fd5b505050602080860151604080516001600160a01b0390921682529181018590529081018390527f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e915060600160405180910390a160208085015160408087015181516001600160a01b039384168152908316938101939093528201859052606082018c90528a8116608083015289169033907f84e4b114d7cc75c5991508169b879228cf0ae428ba30144d51b8fc6a674aa9a89060a0015b60405180910390a350505050611c4c6001600355565b95945050505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091906109039082908690611c8f9087906148ad565b6134f7565b6004546000906001600160701b031680611caf576000611cdd565b600181901b611cc16103e860646148c0565b62ffffff16600654611cd3919061485e565b611cdd919061488b565b91505090565b60098181548110611cf357600080fd5b6000918252602090912001546001600160a01b0316905081565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8f9190614724565b6001600160a01b0316336001600160a01b031614611dd45760405162461bcd60e51b81526020600482015260026024820152614f4560f01b60448201526064016108d8565b600754811115611e0f5760405162461bcd60e51b81526004016108d890602080825260049082015263125495d560e21b604082015260600190565b60088190556040518181527f77f0773cce90b3c7a365117b2463a279ec138c4ab7a241d604f91ebabd8fc25690602001610abd565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611f0d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ed4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef89190614724565b6001600160a01b0316336001600160a01b0316145b80611faa57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f959190614724565b6001600160a01b0316336001600160a01b0316145b611fdb5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b60015b81518110156120a05781611ff360018361484b565b81518110612003576120036148e7565b60200260200101516001600160a01b0316828281518110612026576120266148e7565b60200260200101516001600160a01b0316116120905760405162461bcd60e51b8152602060048201526024808201527f616c6c6f77206c697374206d75737420626520756e6971756520616e6420736f6044820152631c9d195960e21b60648201526084016108d8565b612099816148fd565b9050611fde565b50600060098054806020026020016040519081016040528092919081815260200182805480156120f957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120db575b5050505050905060005b8151811015612166576000600a6000848481518110612124576121246148e7565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905561215f816148fd565b9050612103565b50815161217a90600990602085019061427a565b507f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006000805b85518110156122e957836001600160a01b03168682815181106121e6576121e66148e7565b60200260200101516001600160a01b0316141580156122305750826001600160a01b031686828151811061221c5761221c6148e7565b60200260200101516001600160a01b031614155b156122d9576001600a600088848151811061224d5761224d6148e7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600c60008783815181106122a2576122a26148e7565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054826122d691906148ad565b91505b6122e2816148fd565b90506121c1565b5060068190556040517fc2d08e7ae40f88bd169469bbcfa69c8213cb98772e0bab7de792256c59139eec9061231f908790614916565b60405180910390a15050505050565b6000612338613880565b600b5460ff161561236f5760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6004546001600160701b0380821691600160701b90041660006123b17f00000000000000000000000000000000000000000000000000000000000000006139fa565b905060006123de7f00000000000000000000000000000000000000000000000000000000000000006139fa565b905060006123ec858461484b565b905060006123fa858461484b565b9050600061240760025490565b905080600003612444576103e8612426612421848661485e565b613bee565b612430919061484b565b975061243f60006103e8613cd6565b61246a565b61246787612452838661485e565b61245c919061488b565b87611147848661485e565b97505b6000612474611c94565b9050806124846103e860646148c0565b62ffffff1661249391906148ad565b6124a06103e860646148c0565b6124af9062ffffff168b61485e565b6124b9919061488b565b9850600089116124f15760405162461bcd60e51b8152602060048201526003602482015262494c4d60e81b60448201526064016108d8565b6124fb8a8a613cd6565b6125058686613aff565b896001600160a01b03167f94c792774c59479f7bd68442f3af3691c02123a5aabee8b6f9116d8af8aa666985858c61253c60025490565b60408051948552602085019390935291830152606082015260800160405180910390a250505050505050506125716001600355565b919050565b600080612581613880565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060006125ce836139fa565b905060006125db836139fa565b905060006125e8306139fa565b905060006125f560025490565b905080612602838661485e565b61260c919061488b565b975080612619838561485e565b612623919061488b565b96506000881180156126355750600087115b6126675760405162461bcd60e51b815260206004820152600360248201526224a62160e91b60448201526064016108d8565b6126713083613d3f565b61267c868a8a6138d9565b612687858a896138d9565b6000612691611c94565b905080156127a75760005b6009548110156127a5576000600982815481106126bb576126bb6148e7565b60009182526020808320909101546001600160a01b0316808352600d9091526040909120549091508015612792576000856126f6888461485e565b612700919061488b565b905061270d838f836138d9565b6001600160a01b0383166000908152600c602052604090205486612731898361485e565b61273b919061488b565b612745908261484b565b6001600160a01b0385166000908152600c60205260409020819055600680549091018290039055612776828461484b565b6001600160a01b0385166000908152600d602052604090205550505b50508061279e906148fd565b905061269c565b505b6127b0876139fa565b94506127bb866139fa565b93506127c78585613aff565b6001600160a01b038a16337fa476cebfbe7485684f5578d84d8a64a8afe93a0a2a3047bd6f3e681e108b8f118b8b6127fe60025490565b6040805193845260208401929092529082015260600160405180910390a35050505050505061282d6001600355565b915091565b61283a613e71565b60008261ffff16118015612852575060008161ffff16115b801561286357506103e88261ffff16105b801561287457506103e88161ffff16105b6128a65760405162461bcd60e51b815260206004820152600360248201526249464360e81b60448201526064016108d8565b600480546001600160e01b0316600160e01b61ffff8581169182027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217600160f01b928516928302179092556040805192835260208301919091527faa1ebd1f8841401ae5e1a0f2febc87d5f597ae458fca8277cd0e43b92633183c91015b60405180910390a15050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156129d05760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016108d8565b610ae182868684036134f7565b6129e5613e71565b60008111612a1b5760405162461bcd60e51b815260206004820152600360248201526212549560ea1b60448201526064016108d8565b60078190556040518181527f047f24f47d2c93ef7523cb3c84c3b367df61e4899214a2a48784cfa09da91fdf90602001610abd565b6000336109038185856136ad565b612a66613880565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ac4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae89190614724565b6001600160a01b0316336001600160a01b0316148015612b115750600854612b0e611c94565b10155b80612bae57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370905dce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b999190614724565b6001600160a01b0316336001600160a01b0316145b612bdf5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b6001600160a01b0382166000908152600a602052604090205460ff16612c2d5760405162461bcd60e51b8152602060048201526003602482015262544e5760e81b60448201526064016108d8565b600080826001600160a01b031663aa6ca8086040518163ffffffff1660e01b81526004016040805180830381865afa158015612c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c919190614963565b91509150600080846001600160a01b031662113e086040518163ffffffff1660e01b81526004016040805180830381865afa158015612cd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cf891906149a9565b6001600160701b031691506001600160701b03169150856001600160a01b0316846001600160a01b031614612d2c57919291905b6001600160a01b038681166000908152600d6020526040902054907f000000000000000000000000000000000000000000000000000000000000000081169085161480612daa57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b8015612e5457506040516334a2a5c360e11b81526001600160a01b0388811660048301528581166024830152808816917f0000000000000000000000000000000000000000000000000000000000000000909116906369454b8690604401602060405180830381865afa158015612e25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e499190614724565b6001600160a01b0316145b612e865760405162461bcd60e51b81526020600482015260036024820152620494e560ec1b60448201526064016108d8565b6001600160a01b0387166000908152600c60209081526040808320805460068054919091039055839055600d909152812055612ec38787836138d9565b856001600160a01b031663e9dcafaa612f438386868b6001600160a01b031663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3a91906149dc565b61ffff16613f6d565b604080516000815260208101918290526001600160e01b031960e085901b16909152612f77919088903090602481016149f9565b6020604051808303816000875af1158015612f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fba9190614a35565b50612fe76113b47f00000000000000000000000000000000000000000000000000000000000000006139fa565b7f3f78f965596026d67092e66b7de2aaf2c33839a6b15485c4dec57f03e35e8a3e876000613013611c94565b604080516001600160a01b03909416845260208401929092529082015260600160405180910390a1505050505061304a6001600355565b5050565b600061305d6103e860646148c0565b62ffffff16905090565b6000613071613880565b600b5460ff16156130a85760405162461bcd60e51b81526020600482015260016024820152604360f81b60448201526064016108d8565b6001600160a01b038416158015906130f257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b801561313057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614155b6131615760405162461bcd60e51b8152602060048201526002602482015261125560f21b60448201526064016108d8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b031614806131d257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b6132045760405162461bcd60e51b815260206004820152600360248201526213939560ea1b60448201526064016108d8565b6000861161323a5760405162461bcd60e51b815260206004820152600360248201526249414f60e81b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b03161461329b577f00000000000000000000000000000000000000000000000000000000000000006132bd565b7f00000000000000000000000000000000000000000000000000000000000000005b60045490915060009081906133099084907f0000000000000000000000000000000000000000000000000000000000000000906001600160701b0380821691600160701b900416613fbb565b915091508089106133425760405162461bcd60e51b8152602060048201526003602482015262414f4560e81b60448201526064016108d8565b61334d88888b6138d9565b600061336f8a84846004601c9054906101000a900461ffff1661ffff16613b99565b905085156133d55760405163cc1fd73160e01b8152339063cc1fd731906133a29087908d9086908d908d906004016147e1565b600060405180830381600087803b1580156133bc57600080fd5b505af11580156133d0573d6000803e3d6000fd5b505050505b826133df856139fa565b6133e9919061484b565b94506000851180156133fb5750808510155b61342d5760405162461bcd60e51b815260206004820152600360248201526249494160e81b60448201526064016108d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b03161490506134a08161347d576134788c8561484b565b613487565b61348787866148ad565b82613496576113dd88876148ad565b6113dd8d8661484b565b50604080516001600160a01b0386811682528b81166020830152918101839052606081018c90529089169033907f54787c404bb33c88e86f4baf88183a3b0141d0a848e6a9f7a13b66ae3a9b73d190608001611c36565b6001600160a01b0383166135595760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016108d8565b6001600160a01b0382166135ba5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016108d8565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146136a7578181101561369a5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016108d8565b6136a784848484036134f7565b50505050565b6001600160a01b0383166137295760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016108d8565b6001600160a01b03821661378b5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016108d8565b6001600160a01b0383166000908152602081905260409020548181101561381a5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016108d8565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36136a7565b6002600354036138d25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016108d8565b6002600355565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261392b908490613fee565b505050565b60008084116139815760405162461bcd60e51b815260206004820152601a60248201527f56535741503a20494e53554646494349454e545f414d4f554e5400000000000060448201526064016108d8565b6000831180156139915750600082115b6139dd5760405162461bcd60e51b815260206004820152601d60248201527f56535741503a20494e53554646494349454e545f4c495155494449545900000060448201526064016108d8565b826139e8838661485e565b6139f2919061488b565b949350505050565b604051306024820152600090819081906001600160a01b0385169060440160408051601f198184030181529181526020820180516001600160e01b03166370a0823160e01b17905251613a4d9190614a4e565b600060405180830381855afa9150503d8060008114613a88576040519150601f19603f3d011682016040523d82523d6000602084013e613a8d565b606091505b5091509150818015613aa157506020815110155b613ad35760405162461bcd60e51b815260206004820152600360248201526223212360e91b60448201526064016108d8565b808060200190518101906139f29190614a35565b6000818310613af65781613af8565b825b9392505050565b600580546fffffffffffffffffffffffffffffffff1916436001600160801b0316179055600480546001600160e01b031916600160701b6001600160701b038481169182026dffffffffffffffffffffffffffff1916929092179185169182179092556040805191825260208201929092527fa74621c1abba1dca03b6708d02443d60ddfd3f4273745060c4355afc9daa52c69101612927565b6000806103e8613ba9878761485e565b613bb3919061485e565b9050600083613bc2888761484b565b613bcc919061485e565b9050613bd8818361488b565b613be39060016148ad565b979650505050505050565b600081600003613c0057506000919050565b60006001613c0d846140d3565b901c6001901b90506001818481613c2657613c26614875565b048201901c90506001818481613c3e57613c3e614875565b048201901c90506001818481613c5657613c56614875565b048201901c90506001818481613c6e57613c6e614875565b048201901c90506001818481613c8657613c86614875565b048201901c90506001818481613c9e57613c9e614875565b048201901c90506001818481613cb657613cb6614875565b048201901c9050613af881828581613cd057613cd0614875565b04613ae7565b8060026000828254613ce891906148ad565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038216613d9f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016108d8565b6001600160a01b03821660009081526020819052604090205481811015613e135760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016108d8565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef39190614724565b6001600160a01b0316336001600160a01b03161480613f3a5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b613f6b5760405162461bcd60e51b81526020600482015260026024820152614f4160f01b60448201526064016108d8565b565b600080613f7a838761485e565b90506000613f88858361485e565b9050600082613f996103e88961485e565b613fa391906148ad565b9050613faf818361488b565b98975050505050505050565b600080856001600160a01b0316856001600160a01b031614613fde578284613fe1565b83835b9097909650945050505050565b6000614043826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166141679092919063ffffffff16565b80519091501561392b57808060200190518101906140619190614a6a565b61392b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108d8565b600080608083901c156140e857608092831c92015b604083901c156140fa57604092831c92015b602083901c1561410c57602092831c92015b601083901c1561411e57601092831c92015b600883901c1561413057600892831c92015b600483901c1561414257600492831c92015b600283901c1561415457600292831c92015b600183901c156109095760010192915050565b60606139f2848460008585600080866001600160a01b0316858760405161418e9190614a4e565b60006040518083038185875af1925050503d80600081146141cb576040519150601f19603f3d011682016040523d82523d6000602084013e6141d0565b606091505b5091509150613be3878383876060831561424b578251600003614244576001600160a01b0385163b6142445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108d8565b50816139f2565b6139f283838151156142605781518083602001fd5b8060405162461bcd60e51b81526004016108d8919061435c565b8280548282559060005260206000209081019282156142e7579160200282015b828111156142e757825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0390911617825560209092019160019091019061429a565b506142f39291506142f7565b5090565b5b808211156142f357600081556001016142f8565b60005b8381101561432757818101518382015260200161430f565b50506000910152565b6000815180845261434881602086016020860161430c565b601f01601f19169290920160200192915050565b602081526000613af86020830184614330565b6001600160a01b038116811461438457600080fd5b50565b6000806040838503121561439a57600080fd5b82356143a58161436f565b946020939093013593505050565b6000602082840312156143c557600080fd5b81356001600160801b0381168114613af857600080fd5b6000806000606084860312156143f157600080fd5b83356143fc8161436f565b9250602084013561440c8161436f565b929592945050506040919091013590565b60008083601f84011261442f57600080fd5b50813567ffffffffffffffff81111561444757600080fd5b60208301915083602082850101111561445f57600080fd5b9250929050565b60008060008060008060a0878903121561447f57600080fd5b8635955060208701356144918161436f565b945060408701356144a18161436f565b935060608701359250608087013567ffffffffffffffff8111156144c457600080fd5b6144d089828a0161441d565b979a9699509497509295939492505050565b6000806000806000608086880312156144fa57600080fd5b85359450602086013561450c8161436f565b9350604086013561451c8161436f565b9250606086013567ffffffffffffffff81111561453857600080fd5b6145448882890161441d565b969995985093965092949392505050565b60006020828403121561456757600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156145a8576145a861456e565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156145d7576145d761456e565b604052919050565b600060208083850312156145f257600080fd5b823567ffffffffffffffff8082111561460a57600080fd5b818501915085601f83011261461e57600080fd5b8135818111156146305761463061456e565b8060051b91506146418483016145ae565b818152918301840191848101908884111561465b57600080fd5b938501935b83851015613faf57843592506146758361436f565b8282529385019390850190614660565b60006020828403121561469757600080fd5b8135613af88161436f565b61ffff8116811461438457600080fd5b600080604083850312156146c557600080fd5b82356146d0816146a2565b915060208301356146e0816146a2565b809150509250929050565b600080604083850312156146fe57600080fd5b82356147098161436f565b915060208301356146e08161436f565b80516125718161436f565b60006020828403121561473657600080fd5b8151613af88161436f565b6000610100828403121561475457600080fd5b61475c614584565b825162ffffff8116811461476f57600080fd5b815261477d60208401614719565b602082015261478e60408401614719565b604082015260608301516060820152608083015160808201526147b360a08401614719565b60a08201526147c460c08401614719565b60c08201526147d560e08401614719565b60e08201529392505050565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561090957610909614835565b808202811582820484141761090957610909614835565b634e487b7160e01b600052601260045260246000fd5b6000826148a857634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561090957610909614835565b62ffffff8181168382160280821691908281146148df576148df614835565b505092915050565b634e487b7160e01b600052603260045260246000fd5b60006001820161490f5761490f614835565b5060010190565b6020808252825182820181905260009190848201906040850190845b818110156149575783516001600160a01b031683529284019291840191600101614932565b50909695505050505050565b6000806040838503121561497657600080fd5b82516149818161436f565b60208401519092506146e08161436f565b80516001600160701b038116811461257157600080fd5b600080604083850312156149bc57600080fd5b6149c583614992565b91506149d360208401614992565b90509250929050565b6000602082840312156149ee57600080fd5b8151613af8816146a2565b84815260006001600160a01b03808616602084015280851660408401525060806060830152614a2b6080830184614330565b9695505050505050565b600060208284031215614a4757600080fd5b5051919050565b60008251614a6081846020870161430c565b9190910192915050565b600060208284031215614a7c57600080fd5b81518015158114613af857600080fdfea164736f6c6343000812000aa164736f6c6343000812000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.