Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
SmartFarmingManager
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./utils/ReentrancyGuard.sol"; import "./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/external/IStargateComposerWithRetry.sol"; import "./access/Manageable.sol"; import "./storage/SmartFarmingManagerStorage.sol"; import "./lib/WadRayMath.sol"; import "./lib/CrossChainLib.sol"; error SyntheticDoesNotExist(); error PoolIsNull(); error FlashRepaySlippageTooHigh(); error LeverageTooLow(); error LeverageTooHigh(); error LeverageSlippageTooHigh(); error PositionIsNotHealthy(); error AmountIsZero(); error AmountIsTooHigh(); error DepositTokenDoesNotExist(); error AddressIsNull(); error NewValueIsSameAsCurrent(); error CrossChainRequestInvalidKey(); error SenderIsNotCrossChainDispatcher(); error CrossChainRequestCompletedAlready(); error TokenInIsNull(); error SenderIsNotAccount(); /** * @title SmartFarmingManager contract */ contract SmartFarmingManager is ReentrancyGuard, Manageable, SmartFarmingManagerStorageV1 { using SafeERC20 for IERC20; using SafeERC20 for ISyntheticToken; using WadRayMath for uint256; string public constant VERSION = "1.3.0"; /// @notice Emitted when a cross-chain leverage request is finalized event CrossChainLeverageFinished(uint256 indexed id); /// @notice Emitted when a cross-chain leverage request is created event CrossChainLeverageStarted(uint256 indexed id); /// @notice Emitted when a cross-chain flash repay request is finalized event CrossChainFlashRepayFinished(uint256 indexed id); /// @notice Emitted when a cross-chain flash repay request is created event CrossChainFlashRepayStarted(uint256 indexed id); /// @notice Emitted when debt is flash repaid event FlashRepaid( ISyntheticToken indexed syntheticToken, IDepositToken indexed depositToken, uint256 withdrawn, uint256 repaid ); /// @notice Emitted when deposit is leveraged event Leveraged( IERC20 indexed tokenIn, IDepositToken indexed depositToken, ISyntheticToken indexed syntheticToken, uint256 leverage, uint256 amountIn, uint256 issued, uint256 deposited ); /** * @dev Throws if sender isn't a valid ProxyOFT contract */ modifier onlyIfCrossChainDispatcher() { if (msg.sender != address(crossChainDispatcher())) revert SenderIsNotCrossChainDispatcher(); _; } /** * @dev Throws if deposit token doesn't exist */ modifier onlyIfDepositTokenExists(IDepositToken depositToken_) { if (!pool.doesDepositTokenExist(depositToken_)) revert DepositTokenDoesNotExist(); _; } /** * @dev Throws if synthetic token doesn't exist */ modifier onlyIfSyntheticTokenExists(ISyntheticToken syntheticToken_) { if (!pool.doesSyntheticTokenExist(syntheticToken_)) revert SyntheticDoesNotExist(); _; } constructor() { _disableInitializers(); } function initialize(IPool pool_) public initializer { if (address(pool_) == address(0)) revert PoolIsNull(); __ReentrancyGuard_init(); __Manageable_init(pool_); } /** * @notice Get the Cross-chain dispatcher contract */ function crossChainDispatcher() public view returns (ICrossChainDispatcher _crossChainDispatcher) { return pool.poolRegistry().crossChainDispatcher(); } /*** * @notice Cross-chain flash debt repayment * @dev Not calling `whenNotShutdown` here because nested function already does it * @param syntheticToken_ The debt token to repay * @param depositToken_ The collateral to withdraw * @param withdrawAmount_ The amount to withdraw * @param bridgeToken_ The asset that will be bridged out and used to swap for msAsset * @param bridgeTokenAmountMin_ The minimum amount out when converting collateral for bridgeToken if they aren't the same (slippage check) * @param swapAmountOutMin_ The minimum amount out from the bridgeToken->msAsset swap (slippage check) * @param repayAmountMin_ The minimum amount to repay (slippage check) * @param lzArgs_ The LayerZero params (See: `Quoter.getFlashRepaySwapAndCallbackLzArgs()`) */ function crossChainFlashRepay( ISyntheticToken syntheticToken_, IDepositToken depositToken_, uint256 withdrawAmount_, IERC20 bridgeToken_, uint256 bridgeTokenAmountMin_, uint256 swapAmountOutMin_, uint256 repayAmountMin_, bytes calldata lzArgs_ ) external payable override nonReentrant onlyIfDepositTokenExists(depositToken_) onlyIfSyntheticTokenExists(syntheticToken_) { if (withdrawAmount_ == 0) revert AmountIsZero(); ICrossChainDispatcher _crossChainDispatcher; { IDebtToken _debtToken = pool.debtTokenOf(syntheticToken_); _debtToken.accrueInterest(); if (repayAmountMin_ > _debtToken.balanceOf(msg.sender)) revert AmountIsTooHigh(); _crossChainDispatcher = crossChainDispatcher(); } uint256 _amountIn; { // 1. withdraw collateral // Note: No need to check healthy because this function ensures withdrawing only from unlocked balance (_amountIn, ) = depositToken_.withdrawFrom(msg.sender, withdrawAmount_); // 2. swap collateral for bridge token _amountIn = _swap({ swapper_: swapper(), tokenIn_: _collateralOf(depositToken_), tokenOut_: bridgeToken_, amountIn_: _amountIn, amountOutMin_: bridgeTokenAmountMin_, to_: address(_crossChainDispatcher) }); } // 3. store request and trigger swap _triggerFlashRepaySwap({ crossChainDispatcher_: _crossChainDispatcher, tokenIn_: bridgeToken_, tokenOut_: syntheticToken_, amountIn_: _amountIn, swapAmountOutMin_: swapAmountOutMin_, repayAmountMin_: repayAmountMin_, lzArgs_: lzArgs_ }); } /** * @dev Stores flash repay cross-chain request and triggers swap on the destination chain */ function _triggerFlashRepaySwap( ICrossChainDispatcher crossChainDispatcher_, IERC20 tokenIn_, ISyntheticToken tokenOut_, uint256 amountIn_, uint256 swapAmountOutMin_, uint256 repayAmountMin_, bytes calldata lzArgs_ ) private { uint256 _id = _nextCrossChainRequestId(); (uint16 _dstChainId, , ) = CrossChainLib.decodeLzArgs(lzArgs_); crossChainFlashRepays[_id] = CrossChainFlashRepay({ dstChainId: _dstChainId, syntheticToken: tokenOut_, repayAmountMin: repayAmountMin_, account: msg.sender, finished: false }); crossChainDispatcher_.triggerFlashRepaySwap{value: msg.value}({ id_: _id, account_: payable(msg.sender), tokenIn_: address(tokenIn_), tokenOut_: address(tokenOut_), amountIn_: amountIn_, amountOutMin_: swapAmountOutMin_, lzArgs_: lzArgs_ }); emit CrossChainFlashRepayStarted(_id); } /** * @notice Finalize cross-chain flash debt repayment process * @dev Receives msAsset from L1 and use it to repay * @param id_ The id of the request * @param swapAmountOut_ The msAsset amount received from L1 swap * @return _repaid The debt amount repaid */ function crossChainFlashRepayCallback( uint256 id_, uint256 swapAmountOut_ ) external override whenNotShutdown nonReentrant onlyIfCrossChainDispatcher returns (uint256 _repaid) { CrossChainFlashRepay memory _request = crossChainFlashRepays[id_]; if (_request.account == address(0)) revert CrossChainRequestInvalidKey(); if (_request.finished) revert CrossChainRequestCompletedAlready(); // 1. update state crossChainFlashRepays[id_].finished = true; // 2. transfer synthetic token swapAmountOut_ = _safeTransferFrom(_request.syntheticToken, msg.sender, swapAmountOut_); // 3. repay debt (_repaid, ) = pool.debtTokenOf(_request.syntheticToken).repay(_request.account, swapAmountOut_); if (_repaid < _request.repayAmountMin) revert FlashRepaySlippageTooHigh(); emit CrossChainFlashRepayFinished(id_); } /*** * @notice Cross-chain Leverage * @dev Not calling `whenNotShutdown` here because nested function already does it * @param tokenIn_ The asset to deposit and that'll be bridged in after swapping from msAsset * @param depositToken_ The collateral to deposit * @param syntheticToken_ The msAsset to mint * @param amountIn_ The amount to deposit * @param leverage_ The leverage X param (e.g. 1.5e18 for 1.5X) * @param swapAmountOutMin_ The minimum amount out from msAsset->bridgeToken swap (slippage check) * @param depositAmountMin_ The minimum final amount to deposit (slippage check) * @param lzArgs_ The LayerZero params (See: `Quoter.getLeverageSwapAndCallbackLzArgs()`) */ function crossChainLeverage( IERC20 tokenIn_, IDepositToken depositToken_, ISyntheticToken syntheticToken_, uint256 amountIn_, uint256 leverage_, uint256 swapAmountOutMin_, uint256 depositAmountMin_, bytes calldata lzArgs_ ) external payable override nonReentrant onlyIfDepositTokenExists(depositToken_) onlyIfSyntheticTokenExists(syntheticToken_) { IERC20 _tokenIn = tokenIn_; // stack too deep if (amountIn_ == 0) revert AmountIsZero(); if (leverage_ <= 1e18) revert LeverageTooLow(); if (leverage_ > uint256(1e18).wadDiv(1e18 - depositToken_.collateralFactor())) revert LeverageTooHigh(); if (address(_tokenIn) == address(0)) revert TokenInIsNull(); uint256 _debtAmount; uint256 _issued; { // 1. deposit tokenIn amountIn_ = _safeTransferFrom(_tokenIn, msg.sender, amountIn_); // 2. mint synth _debtAmount = _calculateLeverageDebtAmount(_tokenIn, syntheticToken_, amountIn_, leverage_); (_issued, ) = pool.debtTokenOf(syntheticToken_).flashIssue(address(crossChainDispatcher()), _debtAmount); } // 3. store request and trigger swap _triggerCrossChainLeverageSwap({ depositToken_: depositToken_, depositedAmount_: amountIn_, debtAmount_: _debtAmount, tokenIn_: syntheticToken_, tokenOut_: _tokenIn, swapAmountIn_: _issued, swapAmountOutMin_: swapAmountOutMin_, depositAmountMin_: depositAmountMin_, lzArgs_: lzArgs_ }); } /** * @dev Stores leverage cross-chain request and triggers swap on the destination chain */ function _triggerCrossChainLeverageSwap( IDepositToken depositToken_, uint256 depositedAmount_, uint256 debtAmount_, ISyntheticToken tokenIn_, IERC20 tokenOut_, uint256 swapAmountIn_, uint256 swapAmountOutMin_, uint256 depositAmountMin_, bytes calldata lzArgs_ ) private { uint256 _id = _nextCrossChainRequestId(); { (uint16 _dstChainId, , ) = CrossChainLib.decodeLzArgs(lzArgs_); crossChainLeverages[_id] = CrossChainLeverage({ dstChainId: _dstChainId, bridgeToken: tokenOut_, depositToken: depositToken_, syntheticToken: tokenIn_, depositAmountMin: depositAmountMin_, bridgeTokenAmountIn: depositedAmount_, debtAmount: debtAmount_, account: msg.sender, finished: false }); } crossChainDispatcher().triggerLeverageSwap{value: msg.value}({ id_: _id, account_: payable(msg.sender), tokenIn_: address(tokenIn_), tokenOut_: address(tokenOut_), amountIn_: swapAmountIn_, amountOutMin: swapAmountOutMin_, lzArgs_: lzArgs_ }); emit CrossChainLeverageStarted(_id); } /** * @notice Finalize cross-chain leverage process * @dev Receives bridged token (aka naked token) use it to deposit * @param id_ The id of the request * @param swapAmountOut_ The amount received from swap * @return _deposited The amount deposited */ function crossChainLeverageCallback( uint256 id_, uint256 swapAmountOut_ ) external override whenNotShutdown nonReentrant onlyIfCrossChainDispatcher returns (uint256 _deposited) { CrossChainLeverage memory _request = crossChainLeverages[id_]; if (_request.account == address(0)) revert CrossChainRequestInvalidKey(); if (_request.finished) revert CrossChainRequestCompletedAlready(); IERC20 _collateral = _collateralOf(_request.depositToken); // 1. update state crossChainLeverages[id_].finished = true; // 2. transfer swap's tokenOut (aka bridged token) swapAmountOut_ = _safeTransferFrom(_request.bridgeToken, msg.sender, swapAmountOut_); // 3. swap bridged token for collateral if needed uint256 _bridgeTokenAmount = _request.bridgeTokenAmountIn + swapAmountOut_; uint256 _depositAmount = _request.bridgeToken == _collateral ? _bridgeTokenAmount : _swap(swapper(), _request.bridgeToken, _collateral, _bridgeTokenAmount, 0); if (_depositAmount < _request.depositAmountMin) revert LeverageSlippageTooHigh(); // 4. deposit collateral _collateral.safeApprove(address(_request.depositToken), 0); _collateral.safeApprove(address(_request.depositToken), _depositAmount); (_deposited, ) = _request.depositToken.deposit(_depositAmount, _request.account); // 5. mint debt IPool _pool = pool; _pool.debtTokenOf(_request.syntheticToken).mint(_request.account, _request.debtAmount); // 6. check the health of the outcome position (bool _isHealthy, , , , ) = _pool.debtPositionOf(_request.account); if (!_isHealthy) revert PositionIsNotHealthy(); emit CrossChainLeverageFinished(id_); } /** * @notice Flash debt repayment * @param syntheticToken_ The debt token to repay * @param depositToken_ The collateral to withdraw * @param withdrawAmount_ The amount to withdraw * @param repayAmountMin_ The minimum amount to repay (slippage check) */ function flashRepay( ISyntheticToken syntheticToken_, IDepositToken depositToken_, uint256 withdrawAmount_, uint256 repayAmountMin_ ) external override whenNotShutdown nonReentrant onlyIfDepositTokenExists(depositToken_) onlyIfSyntheticTokenExists(syntheticToken_) returns (uint256 _withdrawn, uint256 _repaid) { if (withdrawAmount_ == 0) revert AmountIsZero(); if (withdrawAmount_ > depositToken_.balanceOf(msg.sender)) revert AmountIsTooHigh(); IPool _pool = pool; IDebtToken _debtToken = _pool.debtTokenOf(syntheticToken_); if (repayAmountMin_ > _debtToken.balanceOf(msg.sender)) revert AmountIsTooHigh(); // 1. withdraw collateral (_withdrawn, ) = depositToken_.flashWithdraw(msg.sender, withdrawAmount_); // 2. swap it for synth uint256 _amountToRepay = _swap(swapper(), _collateralOf(depositToken_), syntheticToken_, _withdrawn, 0); // 3. repay debt (_repaid, ) = _debtToken.repay(msg.sender, _amountToRepay); if (_repaid < repayAmountMin_) revert FlashRepaySlippageTooHigh(); // 4. check the health of the outcome position (bool _isHealthy, , , , ) = _pool.debtPositionOf(msg.sender); if (!_isHealthy) revert PositionIsNotHealthy(); emit FlashRepaid(syntheticToken_, depositToken_, _withdrawn, _repaid); } /** * @notice Leverage yield position * @param tokenIn_ The token to transfer * @param depositToken_ The collateral to deposit * @param syntheticToken_ The msAsset to mint * @param amountIn_ The amount to deposit * @param leverage_ The leverage X param (e.g. 1.5e18 for 1.5X) * @param depositAmountMin_ The min final deposit amount (slippage) */ function leverage( IERC20 tokenIn_, IDepositToken depositToken_, ISyntheticToken syntheticToken_, uint256 amountIn_, uint256 leverage_, uint256 depositAmountMin_ ) external override whenNotShutdown nonReentrant onlyIfDepositTokenExists(depositToken_) onlyIfSyntheticTokenExists(syntheticToken_) returns (uint256 _deposited, uint256 _issued) { if (amountIn_ == 0) revert AmountIsZero(); if (leverage_ <= 1e18) revert LeverageTooLow(); if (leverage_ > uint256(1e18).wadDiv(1e18 - depositToken_.collateralFactor())) revert LeverageTooHigh(); ISwapper _swapper = swapper(); // 1. transfer collateral IERC20 _collateral = _collateralOf(depositToken_); if (address(tokenIn_) == address(0)) tokenIn_ = _collateral; amountIn_ = _safeTransferFrom(tokenIn_, msg.sender, amountIn_); if (tokenIn_ != _collateral) { // Note: `amountOutMin_` is `0` because slippage will be checked later on amountIn_ = _swap(_swapper, tokenIn_, _collateral, amountIn_, 0); } { // 2. mint synth + debt uint256 _debtAmount = _calculateLeverageDebtAmount(_collateral, syntheticToken_, amountIn_, leverage_); IDebtToken _debtToken = pool.debtTokenOf(syntheticToken_); (_issued, ) = _debtToken.flashIssue(address(this), _debtAmount); _debtToken.mint(msg.sender, _debtAmount); } // 3. swap synth for collateral uint256 _depositAmount = amountIn_ + _swap(_swapper, syntheticToken_, _collateral, _issued, 0); if (_depositAmount < depositAmountMin_) revert LeverageSlippageTooHigh(); // 4. deposit collateral _collateral.safeApprove(address(depositToken_), 0); _collateral.safeApprove(address(depositToken_), _depositAmount); (_deposited, ) = depositToken_.deposit(_depositAmount, msg.sender); // 5. check the health of the outcome position (bool _isHealthy, , , , ) = pool.debtPositionOf(msg.sender); if (!_isHealthy) revert PositionIsNotHealthy(); emit Leveraged(tokenIn_, depositToken_, syntheticToken_, leverage_, amountIn_, _issued, _deposited); } /** * @notice Retry cross-chain flash repay callback * @dev This function is used to recover from callback failures due to slippage * @param srcChainId_ The source chain of failed tx * @param srcAddress_ The source path of failed tx * @param nonce_ The nonce of failed tx * @param amount_ The amount of failed tx * @param payload_ The payload of failed tx * @param newRepayAmountMin_ If repayment failed due to slippage, caller may send lower newRepayAmountMin_ */ function retryCrossChainFlashRepayCallback( uint16 srcChainId_, bytes calldata srcAddress_, uint64 nonce_, uint256 amount_, bytes calldata payload_, uint256 newRepayAmountMin_ ) external { (, , uint256 _requestId) = CrossChainLib.decodeFlashRepayCallbackPayload(payload_); CrossChainFlashRepay memory _request = crossChainFlashRepays[_requestId]; if (_request.account == address(0)) revert CrossChainRequestInvalidKey(); if (msg.sender != _request.account) revert SenderIsNotAccount(); if (_request.finished) revert CrossChainRequestCompletedAlready(); crossChainFlashRepays[_requestId].repayAmountMin = newRepayAmountMin_; ICrossChainDispatcher _crossChainDispatcher = crossChainDispatcher(); bytes memory _from = abi.encodePacked(_crossChainDispatcher.crossChainDispatcherOf(srcChainId_)); _request.syntheticToken.proxyOFT().retryOFTReceived({ _srcChainId: srcChainId_, _srcAddress: srcAddress_, _nonce: nonce_, _from: _from, _to: address(_crossChainDispatcher), _amount: amount_, _payload: payload_ }); } /** * @notice Retry cross-chain leverage callback * @dev This function is used to recover from callback failures due to slippage * @param srcChainId_ The source chain of failed tx * @param srcAddress_ The source path of failed tx * @param nonce_ The nonce of failed tx * @param token_ The token of failed tx * @param amount_ The amountIn of failed tx * @param payload_ The payload of failed tx * @param newDepositAmountMin_ If deposit failed due to slippage, caller may send lower newDepositAmountMin_ */ function retryCrossChainLeverageCallback( uint16 srcChainId_, bytes calldata srcAddress_, uint64 nonce_, address token_, uint256 amount_, bytes calldata payload_, uint256 newDepositAmountMin_ ) external { (, uint256 _requestId) = CrossChainLib.decodeLeverageCallbackPayload(payload_); CrossChainLeverage memory _request = crossChainLeverages[_requestId]; if (_request.account == address(0)) revert CrossChainRequestInvalidKey(); if (msg.sender != _request.account) revert SenderIsNotAccount(); if (_request.finished) revert CrossChainRequestCompletedAlready(); crossChainLeverages[_requestId].depositAmountMin = newDepositAmountMin_; ICrossChainDispatcher _crossChainDispatcher = crossChainDispatcher(); address _from = _crossChainDispatcher.crossChainDispatcherOf(srcChainId_); bytes memory _sgReceiveCallData = abi.encodeWithSelector( IStargateReceiver.sgReceive.selector, srcChainId_, abi.encodePacked(_from), // use the caller as the srcAddress (the msg.sender caller the StargateComposer at the source) nonce_, token_, amount_, payload_ ); IStargateComposerWithRetry(address(_crossChainDispatcher.stargateComposer())).clearCachedSwap( srcChainId_, srcAddress_, nonce_, address(_crossChainDispatcher), _sgReceiveCallData ); } /** * @notice Get the swapper contract */ function swapper() public view returns (ISwapper _swapper) { return pool.poolRegistry().swapper(); } /** * @notice Calculate debt to issue for a leverage operation * @param collateral_ The collateral to deposit * @param syntheticToken_ The msAsset to mint * @param amountIn_ The amount to deposit * @param leverage_ The leverage X param (e.g. 1.5e18 for 1.5X) * @return _debtAmount The debt issue */ function _calculateLeverageDebtAmount( IERC20 collateral_, ISyntheticToken syntheticToken_, uint256 amountIn_, uint256 leverage_ ) private view returns (uint256 _debtAmount) { return pool.masterOracle().quote( address(collateral_), address(syntheticToken_), (leverage_ - 1e18).wadMul(amountIn_) ); } /** * @dev `collateral` is a better name than `underlying` * See more: https://github.com/autonomoussoftware/metronome-synth/issues/905 */ function _collateralOf(IDepositToken depositToken_) private view returns (IERC20) { return depositToken_.underlying(); } /** * @dev Generates cross-chain request id by hashing `chainId`+`requestId` in order to avoid * having same id across supported chains * Note: The cross-chain code mostly uses LZ chain ids but in this case, we're using native id. */ function _nextCrossChainRequestId() private returns (uint256 _id) { return uint256(keccak256(abi.encode(block.chainid, ++crossChainRequestsLength))); } /** * @notice Transfer token and check actual amount transferred * @param token_ The token to transfer * @param from_ The account to get tokens from * @param amount_ The amount to transfer * @return _transferred The actual transferred amount */ function _safeTransferFrom(IERC20 token_, address from_, uint256 amount_) private returns (uint256 _transferred) { uint256 _before = token_.balanceOf(address(this)); token_.safeTransferFrom(from_, address(this), amount_); return token_.balanceOf(address(this)) - _before; } /** * @notice Swap assets using Swapper contract * @dev Use `address(this)` as amount out receiver * @param swapper_ The Swapper contract * @param tokenIn_ The token to swap from * @param tokenOut_ The token to swap to * @param amountIn_ The amount in * @param amountOutMin_ The minimum amount out (slippage check) * @return _amountOut The actual amount out */ function _swap( ISwapper swapper_, IERC20 tokenIn_, IERC20 tokenOut_, uint256 amountIn_, uint256 amountOutMin_ ) private returns (uint256 _amountOut) { return _swap(swapper_, tokenIn_, tokenOut_, amountIn_, amountOutMin_, address(this)); } /** * @notice Swap assets using Swapper contract * @param swapper_ The Swapper contract * @param tokenIn_ The token to swap from * @param tokenOut_ The token to swap to * @param amountIn_ The amount in * @param amountOutMin_ The minimum amount out (slippage check) * @param to_ The amount out receiver * @return _amountOut The actual amount out */ function _swap( ISwapper swapper_, IERC20 tokenIn_, IERC20 tokenOut_, uint256 amountIn_, uint256 amountOutMin_, address to_ ) private returns (uint256 _amountOut) { if (tokenIn_ != tokenOut_) { tokenIn_.safeApprove(address(swapper_), 0); tokenIn_.safeApprove(address(swapper_), amountIn_); uint256 _tokenOutBefore = tokenOut_.balanceOf(to_); swapper_.swapExactInput(address(tokenIn_), address(tokenOut_), amountIn_, amountOutMin_, to_); return tokenOut_.balanceOf(to_) - _tokenOutBefore; } else if (to_ != address(this)) { tokenIn_.safeTransfer(to_, amountIn_); } return amountIn_; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol"; import "../interfaces/IGovernable.sol"; import "../interfaces/IManageable.sol"; error SenderIsNotPool(); error SenderIsNotGovernor(); error IsPaused(); error IsShutdown(); error PoolAddressIsNull(); /** * @title Reusable contract that handles accesses */ abstract contract Manageable is IManageable, Initializable { /** * @notice Pool contract */ IPool public pool; /** * @dev Throws if `msg.sender` isn't the pool */ modifier onlyPool() { if (msg.sender != address(pool)) revert SenderIsNotPool(); _; } /** * @dev Throws if `msg.sender` isn't the governor */ modifier onlyGovernor() { if (msg.sender != governor()) revert SenderIsNotGovernor(); _; } /** * @dev Throws if contract is paused */ modifier whenNotPaused() { if (pool.paused()) revert IsPaused(); _; } /** * @dev Throws if contract is shutdown */ modifier whenNotShutdown() { if (pool.everythingStopped()) revert IsShutdown(); _; } // solhint-disable-next-line func-name-mixedcase function __Manageable_init(IPool pool_) internal onlyInitializing { if (address(pool_) == address(0)) revert PoolAddressIsNull(); pool = pool_; } /** * @notice Get the governor * @return _governor The governor */ function governor() public view returns (address _governor) { _governor = IGovernable(address(pool)).governor(); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.2; import "../../../../../openzeppelin-upgradeable/utils/introspection/IERC165Upgradeable.sol"; /** * @dev Interface of the IOFT core standard */ interface IOFTCoreUpgradeable is IERC165Upgradeable { /** * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`) * _dstChainId - L0 defined chain id to send tokens too * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain * _amount - amount of the tokens to transfer * _useZro - indicates to use zro to pay L0 fees * _adapterParam - flexible bytes array to indicate messaging adapter services in L0 */ function estimateSendFee( uint16 _dstChainId, bytes calldata _toAddress, uint _amount, bool _useZro, bytes calldata _adapterParams ) external view returns (uint nativeFee, uint zroFee); /** * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from` * `_from` the owner of token * `_dstChainId` the destination chain identifier * `_toAddress` can be any size depending on the `dstChainId`. * `_amount` the quantity of tokens in wei * `_refundAddress` the address LayerZero refunds if too much message fee is sent * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token) * `_adapterParams` is a flexible bytes array to indicate messaging adapter services */ function sendFrom( address _from, uint16 _dstChainId, bytes calldata _toAddress, uint _amount, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams ) external payable; /** * @dev returns the circulating amount of tokens on current chain */ function circulatingSupply() external view returns (uint); /** * @dev returns the address of the ERC20 token */ function token() external view returns (address); /** * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`) * `_nonce` is the outbound nonce */ event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint _amount); /** * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain. * `_nonce` is the inbound nonce. */ event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint _amount); event SetUseCustomAdapterParams(bool _useCustomAdapterParams); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; import "../IOFTCoreUpgradeable.sol"; /** * @dev Interface of the composable OFT core standard */ interface IComposableOFTCoreUpgradeable is IOFTCoreUpgradeable { function estimateSendAndCallFee( uint16 _dstChainId, bytes calldata _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, bool _useZro, bytes calldata _adapterParams ) external view returns (uint nativeFee, uint zroFee); function sendAndCall( address _from, uint16 _dstChainId, bytes calldata _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams ) external payable; function retryOFTReceived( uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _from, address _to, uint _amount, bytes calldata _payload ) external; event CallOFTReceivedFailure( uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _from, address indexed _to, uint _amount, bytes _payload, bytes _reason ); event CallOFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _hash); event RetryOFTReceivedSuccess(bytes32 _messageHash); event NonContractAddress(address _address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface IOFTReceiverUpgradeable { /** * @dev Called by the OFT contract when tokens are received from source chain. * @param _srcChainId The chain id of the source chain. * @param _srcAddress The address of the OFT token contract on the source chain. * @param _nonce The nonce of the transaction on the source chain. * @param _from The address of the account who calls the sendAndCall() on the source chain. * @param _amount The amount of tokens to transfer. * @param _payload Additional data with no specified format. */ function onOFTReceived( uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _from, uint _amount, bytes calldata _payload ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT 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 pragma solidity ^0.8.0; import "../IERC20.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)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import "./IStargateRouter.sol"; interface IStargateComposer { function swap( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLD, uint256 _minAmountLD, IStargateRouter.lzTxObj memory _lzTxParams, bytes calldata _to, bytes calldata _payload ) external payable; function factory() external view returns (address); function stargateBridge() external view returns (address); function stargateRouter() external view returns (IStargateRouter); function quoteLayerZeroFee( uint16 _dstChainId, uint8 _functionType, bytes calldata _toAddress, bytes calldata _transferAndCallPayload, IStargateRouter.lzTxObj memory _lzTxParams ) external view returns (uint256, uint256); function peers(uint16 _chainId) external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; interface IStargateReceiver { function sgReceive( uint16 _chainId, bytes memory _srcAddress, uint256 _nonce, address _token, uint256 amountLD, bytes memory payload ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; interface IStargateRouter { struct lzTxObj { uint256 dstGasForCall; uint256 dstNativeAmount; bytes dstNativeAddr; } function addLiquidity(uint256 _poolId, uint256 _amountLD, address _to) external; function swap( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLD, uint256 _minAmountLD, lzTxObj memory _lzTxParams, bytes calldata _to, bytes calldata _payload ) external payable; function redeemRemote( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, uint256 _minAmountLD, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function instantRedeemLocal(uint16 _srcPoolId, uint256 _amountLP, address _to) external returns (uint256); function redeemLocal( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function sendCredits( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress ) external payable; function quoteLayerZeroFee( uint16 _dstChainId, uint8 _functionType, bytes calldata _toAddress, bytes calldata _transferAndCallPayload, lzTxObj memory _lzTxParams ) external view returns (uint256, uint256); function clearCachedSwap(uint16 _srcChainId, bytes calldata _srcAddress, uint256 _nonce) external; function factory() external view returns (address); function bridge() external view returns (address); function cachedSwapLookup( uint16 _chainId_, bytes calldata _srcAddress, uint256 _nonce ) external view returns (address token, uint256 amountLD, address to, bytes memory payload); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/IOFTReceiverUpgradeable.sol"; import "../dependencies/stargate-protocol/interfaces/IStargateReceiver.sol"; import "../dependencies/stargate-protocol/interfaces/IStargateRouter.sol"; import "../dependencies/stargate-protocol/interfaces/IStargateComposer.sol"; import "./IProxyOFT.sol"; interface ICrossChainDispatcher is IStargateReceiver, IOFTReceiverUpgradeable { function crossChainDispatcherOf(uint16 chainId_) external view returns (address); function triggerFlashRepaySwap( uint256 id_, address payable account_, address tokenIn_, address tokenOut_, uint256 amountIn_, uint256 amountOutMin_, bytes calldata lzArgs_ ) external payable; function triggerLeverageSwap( uint256 id_, address payable account_, address tokenIn_, address tokenOut_, uint256 amountIn_, uint256 amountOutMin, bytes calldata lzArgs_ ) external payable; function isBridgingActive() external view returns (bool); function flashRepayCallbackTxGasLimit() external view returns (uint64); function flashRepaySwapTxGasLimit() external view returns (uint64); function leverageCallbackTxGasLimit() external view returns (uint64); function leverageSwapTxGasLimit() external view returns (uint64); function lzBaseGasLimit() external view returns (uint256); function stargateComposer() external view returns (IStargateComposer); function stargateSlippage() external view returns (uint256); function stargatePoolIdOf(address token_) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol"; import "./ISyntheticToken.sol"; interface IDebtToken is IERC20Metadata { function lastTimestampAccrued() external view returns (uint256); function isActive() external view returns (bool); function syntheticToken() external view returns (ISyntheticToken); function accrueInterest() external; function debtIndex() external returns (uint256 debtIndex_); function burn(address from_, uint256 amount_) external; function issue(uint256 amount_, address to_) external returns (uint256 _issued, uint256 _fee); function flashIssue(address to_, uint256 amount_) external returns (uint256 _issued, uint256 _fee); function mint(address to_, uint256 amount_) external; function repay(address onBehalfOf_, uint256 amount_) external returns (uint256 _repaid, uint256 _fee); function repayAll(address onBehalfOf_) external returns (uint256 _repaid, uint256 _fee); function quoteIssueIn(uint256 amountToIssue_) external view returns (uint256 _amount, uint256 _fee); function quoteIssueOut(uint256 amount_) external view returns (uint256 _amountToIssue, uint256 _fee); function quoteRepayIn(uint256 amountToRepay_) external view returns (uint256 _amount, uint256 _fee); function quoteRepayOut(uint256 amount_) external view returns (uint256 _amountToRepay, uint256 _fee); function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external; function updateInterestRate(uint256 newInterestRate_) external; function maxTotalSupply() external view returns (uint256); function interestRate() external view returns (uint256); function interestRatePerSecond() external view returns (uint256); function toggleIsActive() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol"; interface IDepositToken is IERC20Metadata { function underlying() external view returns (IERC20); function collateralFactor() external view returns (uint256); function unlockedBalanceOf(address account_) external view returns (uint256); function lockedBalanceOf(address account_) external view returns (uint256); function flashWithdraw(address account_, uint256 amount_) external returns (uint256 _withdrawn, uint256 _fee); function deposit(uint256 amount_, address onBehalfOf_) external returns (uint256 _deposited, uint256 _fee); function quoteDepositIn(uint256 amountToDeposit_) external view returns (uint256 _amount, uint256 _fee); function quoteDepositOut(uint256 amount_) external view returns (uint256 _amountToDeposit, uint256 _fee); function quoteWithdrawIn(uint256 amountToWithdraw_) external view returns (uint256 _amount, uint256 _fee); function quoteWithdrawOut(uint256 amount_) external view returns (uint256 _amountToWithdraw, uint256 _fee); function withdraw(uint256 amount_, address to_) external returns (uint256 _withdrawn, uint256 _fee); function seize(address from_, address to_, uint256 amount_) external; function updateCollateralFactor(uint128 newCollateralFactor_) external; function isActive() external view returns (bool); function toggleIsActive() external; function maxTotalSupply() external view returns (uint256); function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external; function withdrawFrom(address from_, uint256 amount_) external returns (uint256 _withdrawn, uint256 _fee); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @notice FeeProvider interface */ interface IFeeProvider { struct LiquidationFees { uint128 liquidatorIncentive; uint128 protocolFee; } function defaultSwapFee() external view returns (uint256); function depositFee() external view returns (uint256); function issueFee() external view returns (uint256); function liquidationFees() external view returns (uint128 liquidatorIncentive, uint128 protocolFee); function repayFee() external view returns (uint256); function swapFeeFor(address account_) external view returns (uint256); function withdrawFee() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @notice Governable interface */ interface IGovernable { function governor() external view returns (address _governor); function transferGovernorship(address _proposedGovernor) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IPool.sol"; /** * @notice Manageable interface */ interface IManageable { function pool() external view returns (IPool _pool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IPauseable { function paused() external view returns (bool); function everythingStopped() external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IDepositToken.sol"; import "./IDebtToken.sol"; import "./ITreasury.sol"; import "./IRewardsDistributor.sol"; import "./IPoolRegistry.sol"; import "./IFeeProvider.sol"; import "./ISmartFarmingManager.sol"; import "./external/ISwapper.sol"; import "../interfaces/IFeeProvider.sol"; /** * @notice Pool interface */ interface IPool is IPauseable, IGovernable { function debtFloorInUsd() external view returns (uint256); function feeCollector() external view returns (address); function feeProvider() external view returns (IFeeProvider); function maxLiquidable() external view returns (uint256); function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) external view returns (bool); function doesDebtTokenExist(IDebtToken debtToken_) external view returns (bool); function doesDepositTokenExist(IDepositToken depositToken_) external view returns (bool); function depositTokenOf(IERC20 underlying_) external view returns (IDepositToken); function debtTokenOf(ISyntheticToken syntheticToken_) external view returns (IDebtToken); function getDepositTokens() external view returns (address[] memory); function getDebtTokens() external view returns (address[] memory); function getRewardsDistributors() external view returns (address[] memory); function debtOf(address account_) external view returns (uint256 _debtInUsd); function depositOf(address account_) external view returns (uint256 _depositInUsd, uint256 _issuableLimitInUsd); function debtPositionOf( address account_ ) external view returns ( bool _isHealthy, uint256 _depositInUsd, uint256 _debtInUsd, uint256 _issuableLimitInUsd, uint256 _issuableInUsd ); function liquidate( ISyntheticToken syntheticToken_, address account_, uint256 amountToRepay_, IDepositToken depositToken_ ) external returns (uint256 _totalSeized, uint256 _toLiquidator, uint256 _fee); function quoteLiquidateIn( ISyntheticToken syntheticToken_, uint256 totalToSeized_, IDepositToken depositToken_ ) external view returns (uint256 _amountToRepay, uint256 _toLiquidator, uint256 _fee); function quoteLiquidateMax( ISyntheticToken syntheticToken_, address account_, IDepositToken depositToken_ ) external view returns (uint256 _maxAmountToRepay); function quoteLiquidateOut( ISyntheticToken syntheticToken_, uint256 amountToRepay_, IDepositToken depositToken_ ) external view returns (uint256 _totalSeized, uint256 _toLiquidator, uint256 _fee); function quoteSwapIn( ISyntheticToken syntheticTokenIn_, ISyntheticToken syntheticTokenOut_, uint256 amountOut_ ) external view returns (uint256 _amountIn, uint256 _fee); function quoteSwapOut( ISyntheticToken syntheticTokenIn_, ISyntheticToken syntheticTokenOut_, uint256 amountIn_ ) external view returns (uint256 _amountOut, uint256 _fee); function swap( ISyntheticToken syntheticTokenIn_, ISyntheticToken syntheticTokenOut_, uint256 amountIn_ ) external returns (uint256 _amountOut, uint256 _fee); function treasury() external view returns (ITreasury); function masterOracle() external view returns (IMasterOracle); function poolRegistry() external view returns (IPoolRegistry); function addToDepositTokensOfAccount(address account_) external; function removeFromDepositTokensOfAccount(address account_) external; function addToDebtTokensOfAccount(address account_) external; function removeFromDebtTokensOfAccount(address account_) external; function getDepositTokensOfAccount(address account_) external view returns (address[] memory); function getDebtTokensOfAccount(address account_) external view returns (address[] memory); function isSwapActive() external view returns (bool); function smartFarmingManager() external view returns (ISmartFarmingManager); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./external/IMasterOracle.sol"; import "./IPauseable.sol"; import "./IGovernable.sol"; import "./ISyntheticToken.sol"; import "./external/ISwapper.sol"; import "./IQuoter.sol"; import "./ICrossChainDispatcher.sol"; interface IPoolRegistry is IPauseable, IGovernable { function feeCollector() external view returns (address); function isPoolRegistered(address pool_) external view returns (bool); function nativeTokenGateway() external view returns (address); function getPools() external view returns (address[] memory); function registerPool(address pool_) external; function unregisterPool(address pool_) external; function masterOracle() external view returns (IMasterOracle); function updateFeeCollector(address newFeeCollector_) external; function idOfPool(address pool_) external view returns (uint256); function nextPoolId() external view returns (uint256); function swapper() external view returns (ISwapper); function quoter() external view returns (IQuoter); function crossChainDispatcher() external view returns (ICrossChainDispatcher); function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) external view returns (bool _exists); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/IComposableOFTCoreUpgradeable.sol"; interface IProxyOFT is IComposableOFTCoreUpgradeable { function getProxyOFTOf(uint16 chainId_) external view returns (address _proxyOFT); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IPoolRegistry.sol"; import "./IProxyOFT.sol"; interface IQuoter { function quoteCrossChainFlashRepayNativeFee( IProxyOFT proxyOFT_, bytes calldata lzArgs_ ) external view returns (uint256 _nativeFee); function quoteCrossChainLeverageNativeFee( IProxyOFT proxyOFT_, bytes calldata lzArgs_ ) external view returns (uint256 _nativeFee); function quoteLeverageCallbackNativeFee(uint16 dstChainId_) external view returns (uint256 _callbackTxNativeFee); function quoteFlashRepayCallbackNativeFee(uint16 dstChainId_) external view returns (uint256 _callbackTxNativeFee); function getFlashRepaySwapAndCallbackLzArgs( uint16 srcChainId_, uint16 dstChainId_ ) external view returns (bytes memory lzArgs_); function getLeverageSwapAndCallbackLzArgs( uint16 srcChainId_, uint16 dstChainId_ ) external view returns (bytes memory lzArgs_); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/token/ERC20/IERC20.sol"; /** * @notice Reward Distributor interface */ interface IRewardsDistributor { function rewardToken() external view returns (IERC20); function tokenSpeeds(IERC20 token_) external view returns (uint256); function tokensAccruedOf(address account_) external view returns (uint256); function updateBeforeMintOrBurn(IERC20 token_, address account_) external; function updateBeforeTransfer(IERC20 token_, address from_, address to_) external; function claimable(address account_) external view returns (uint256 _claimable); function claimable(address account_, IERC20 token_) external view returns (uint256 _claimable); function claimRewards(address account_) external; function claimRewards(address account_, IERC20[] memory tokens_) external; function claimRewards(address[] memory accounts_, IERC20[] memory tokens_) external; function updateTokenSpeed(IERC20 token_, uint256 newSpeed_) external; function updateTokenSpeeds(IERC20[] calldata tokens_, uint256[] calldata speeds_) external; function tokens(uint256) external view returns (IERC20); function tokenStates(IERC20) external view returns (uint224 index, uint32 timestamp); function accountIndexOf(IERC20, address) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IManageable.sol"; import "./IDepositToken.sol"; import "./IDebtToken.sol"; /** * @notice SmartFarmingManager interface */ interface ISmartFarmingManager { function flashRepay( ISyntheticToken syntheticToken_, IDepositToken depositToken_, uint256 withdrawAmount_, uint256 repayAmountMin_ ) external returns (uint256 _withdrawn, uint256 _repaid); function crossChainFlashRepay( ISyntheticToken syntheticToken_, IDepositToken depositToken_, uint256 withdrawAmount_, IERC20 bridgeToken_, uint256 bridgeTokenAmountMin_, uint256 swapAmountOutMin_, uint256 repayAmountMin_, bytes calldata lzArgs_ ) external payable; function crossChainLeverage( IERC20 tokenIn_, IDepositToken depositToken_, ISyntheticToken syntheticToken_, uint256 amountIn_, uint256 leverage_, uint256 swapAmountOutMin_, uint256 depositAmountMin_, bytes calldata lzArgs_ ) external payable; function crossChainLeverageCallback(uint256 id_, uint256 swapAmountOut_) external returns (uint256 _deposited); function crossChainFlashRepayCallback(uint256 id_, uint256 swapAmountOut_) external returns (uint256 _repaid); function leverage( IERC20 tokenIn_, IDepositToken depositToken_, ISyntheticToken syntheticToken_, uint256 amountIn_, uint256 leverage_, uint256 depositAmountMin_ ) external returns (uint256 _deposited, uint256 _issued); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol"; import "./IDebtToken.sol"; import "./IPoolRegistry.sol"; import "../interfaces/IProxyOFT.sol"; interface ISyntheticToken is IERC20Metadata { function isActive() external view returns (bool); function mint(address to_, uint256 amount_) external; function burn(address from_, uint256 amount) external; function poolRegistry() external view returns (IPoolRegistry); function toggleIsActive() external; function seize(address from_, address to_, uint256 amount_) external; function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external; function updateProxyOFT(IProxyOFT newProxyOFT_) external; function maxTotalSupply() external view returns (uint256); function proxyOFT() external view returns (IProxyOFT); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface ITreasury { function pull(address to_, uint256 amount_) external; function migrateTo(address newTreasury_) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IMasterOracle { function quoteTokenToUsd(address _asset, uint256 _amount) external view returns (uint256 _amountInUsd); function quoteUsdToToken(address _asset, uint256 _amountInUsd) external view returns (uint256 _amount); function quote(address _assetIn, address _assetOut, uint256 _amountIn) external view returns (uint256 _amountOut); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import "../../dependencies/stargate-protocol/interfaces/IStargateComposer.sol"; // Note: Extending interface instead of adding those function to avoid triggering upgrade for other contracts // We may move functions to `IStargateComposer` on the next major upgrade interface IStargateComposerWithRetry is IStargateComposer { function payloadHashes( uint16 _srcChainId, bytes calldata _srcAddress, uint256 _nonce ) external view returns (bytes32); function clearCachedSwap( uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, address _receiver, bytes calldata _sgReceiveCallData ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface ISwapper { function swapExactInput( address tokenIn_, address tokenOut_, uint256 amountIn_, uint256 amountOutMin_, address receiver_ ) external returns (uint256 _amountOut); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; library CrossChainLib { /** * @notice Supported cross-chain operations */ uint8 public constant LEVERAGE = 1; uint8 public constant FLASH_REPAY = 2; function getOperationType(bytes memory payload_) internal pure returns (uint8 _op) { (_op, ) = abi.decode(payload_, (uint8, bytes)); } function encodeLeverageCallbackPayload( address srcSmartFarmingManager_, uint256 requestId_ ) internal pure returns (bytes memory _payload) { return abi.encode(LEVERAGE, abi.encode(srcSmartFarmingManager_, requestId_)); } function decodeLeverageCallbackPayload( bytes memory payload_ ) internal pure returns (address _srcSmartFarmingManager, uint256 _requestId) { (, payload_) = abi.decode(payload_, (uint8, bytes)); return abi.decode(payload_, (address, uint256)); } function encodeFlashRepayCallbackPayload( address srcProxyOFT_, address srcSmartFarmingManager_, uint256 requestId_ ) internal pure returns (bytes memory _payload) { return abi.encode(FLASH_REPAY, abi.encode(srcProxyOFT_, srcSmartFarmingManager_, requestId_)); } function decodeFlashRepayCallbackPayload( bytes memory payload_ ) internal pure returns (address srcProxyOFT_, address _srcSmartFarmingManager, uint256 _requestId) { (, payload_) = abi.decode(payload_, (uint8, bytes)); return abi.decode(payload_, (address, address, uint256)); } function encodeFlashRepaySwapPayload( address srcSmartFarmingManager_, address dstProxyOFT_, uint256 requestId_, address account_, uint256 amountOutMin_ ) internal pure returns (bytes memory _payload) { return abi.encode( FLASH_REPAY, abi.encode(srcSmartFarmingManager_, dstProxyOFT_, requestId_, account_, amountOutMin_) ); } function decodeFlashRepaySwapPayload( bytes memory payload_ ) internal pure returns ( address srcSmartFarmingManager_, address dstProxyOFT_, uint256 requestId_, address account_, uint256 amountOutMin_ ) { (, payload_) = abi.decode(payload_, (uint8, bytes)); return abi.decode(payload_, (address, address, uint256, address, uint256)); } function encodeLeverageSwapPayload( address srcSmartFarmingManager_, address dstProxyOFT_, uint256 requestId_, uint256 sgPoolId_, address account_, uint256 amountOutMin_ ) internal pure returns (bytes memory _payload) { return abi.encode( LEVERAGE, abi.encode(srcSmartFarmingManager_, dstProxyOFT_, requestId_, sgPoolId_, account_, amountOutMin_) ); } function decodeLeverageSwapPayload( bytes memory payload_ ) internal pure returns ( address srcSmartFarmingManager_, address dstProxyOFT_, uint256 requestId_, uint256 sgPoolId_, address account_, uint256 amountOutMin_ ) { (, payload_) = abi.decode(payload_, (uint8, bytes)); return abi.decode(payload_, (address, address, uint256, uint256, address, uint256)); } function encodeLzArgs( uint16 dstChainId_, uint256 callbackNativeFee_, uint64 swapTxGasLimit_ ) internal pure returns (bytes memory _lzArgs) { return abi.encode(dstChainId_, callbackNativeFee_, swapTxGasLimit_); } function decodeLzArgs( bytes memory lzArgs_ ) internal pure returns (uint16 dstChainId_, uint256 callbackNativeFee_, uint64 swapTxGasLimit_) { return abi.decode(lzArgs_, (uint16, uint256, uint64)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @title Math library * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits) * @dev Based on https://github.com/dapphub/ds-math/blob/master/src/math.sol */ library WadRayMath { uint256 internal constant WAD = 1e18; uint256 internal constant HALF_WAD = WAD / 2; uint256 internal constant RAY = 1e27; uint256 internal constant HALF_RAY = RAY / 2; uint256 internal constant WAD_RAY_RATIO = 1e9; /** * @dev Multiplies two wad, rounding half up to the nearest wad * @param a Wad * @param b Wad * @return The result of a*b, in wad */ function wadMul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } return (a * b + HALF_WAD) / WAD; } /** * @dev Divides two wad, rounding half up to the nearest wad * @param a Wad * @param b Wad * @return The result of a/b, in wad */ function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) { return (a * WAD + b / 2) / b; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../interfaces/ISmartFarmingManager.sol"; // solhint-disable var-name-mixedcase, max-states-count abstract contract SmartFarmingManagerStorageV1 is ISmartFarmingManager { /** * @notice Cross-chain Leverage request data */ struct CrossChainLeverage { uint16 dstChainId; IERC20 bridgeToken; IDepositToken depositToken; ISyntheticToken syntheticToken; uint256 bridgeTokenAmountIn; uint256 debtAmount; uint256 depositAmountMin; address account; bool finished; } /** * @notice Cross-chain Flash repay request data */ struct CrossChainFlashRepay { uint16 dstChainId; ISyntheticToken syntheticToken; uint256 repayAmountMin; address account; bool finished; } /** * @notice Cross-chain requests counter */ uint256 public crossChainRequestsLength; /** * @notice Cross-chain leverage requests */ mapping(uint256 => CrossChainLeverage) public crossChainLeverages; /** * @notice Cross-chain flash repay requests */ mapping(uint256 => CrossChainFlashRepay) public crossChainFlashRepays; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol"; /** * @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 is Initializable { // 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; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _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() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmountIsTooHigh","type":"error"},{"inputs":[],"name":"AmountIsZero","type":"error"},{"inputs":[],"name":"CrossChainRequestCompletedAlready","type":"error"},{"inputs":[],"name":"CrossChainRequestInvalidKey","type":"error"},{"inputs":[],"name":"DepositTokenDoesNotExist","type":"error"},{"inputs":[],"name":"FlashRepaySlippageTooHigh","type":"error"},{"inputs":[],"name":"IsShutdown","type":"error"},{"inputs":[],"name":"LeverageSlippageTooHigh","type":"error"},{"inputs":[],"name":"LeverageTooHigh","type":"error"},{"inputs":[],"name":"LeverageTooLow","type":"error"},{"inputs":[],"name":"PoolAddressIsNull","type":"error"},{"inputs":[],"name":"PoolIsNull","type":"error"},{"inputs":[],"name":"PositionIsNotHealthy","type":"error"},{"inputs":[],"name":"SenderIsNotAccount","type":"error"},{"inputs":[],"name":"SenderIsNotCrossChainDispatcher","type":"error"},{"inputs":[],"name":"SyntheticDoesNotExist","type":"error"},{"inputs":[],"name":"TokenInIsNull","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CrossChainFlashRepayFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CrossChainFlashRepayStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CrossChainLeverageFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CrossChainLeverageStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISyntheticToken","name":"syntheticToken","type":"address"},{"indexed":true,"internalType":"contract IDepositToken","name":"depositToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"repaid","type":"uint256"}],"name":"FlashRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"contract IDepositToken","name":"depositToken","type":"address"},{"indexed":true,"internalType":"contract ISyntheticToken","name":"syntheticToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"leverage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"issued","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deposited","type":"uint256"}],"name":"Leveraged","type":"event"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crossChainDispatcher","outputs":[{"internalType":"contract ICrossChainDispatcher","name":"_crossChainDispatcher","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISyntheticToken","name":"syntheticToken_","type":"address"},{"internalType":"contract IDepositToken","name":"depositToken_","type":"address"},{"internalType":"uint256","name":"withdrawAmount_","type":"uint256"},{"internalType":"contract IERC20","name":"bridgeToken_","type":"address"},{"internalType":"uint256","name":"bridgeTokenAmountMin_","type":"uint256"},{"internalType":"uint256","name":"swapAmountOutMin_","type":"uint256"},{"internalType":"uint256","name":"repayAmountMin_","type":"uint256"},{"internalType":"bytes","name":"lzArgs_","type":"bytes"}],"name":"crossChainFlashRepay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"swapAmountOut_","type":"uint256"}],"name":"crossChainFlashRepayCallback","outputs":[{"internalType":"uint256","name":"_repaid","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"crossChainFlashRepays","outputs":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"contract ISyntheticToken","name":"syntheticToken","type":"address"},{"internalType":"uint256","name":"repayAmountMin","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"finished","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenIn_","type":"address"},{"internalType":"contract IDepositToken","name":"depositToken_","type":"address"},{"internalType":"contract ISyntheticToken","name":"syntheticToken_","type":"address"},{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"leverage_","type":"uint256"},{"internalType":"uint256","name":"swapAmountOutMin_","type":"uint256"},{"internalType":"uint256","name":"depositAmountMin_","type":"uint256"},{"internalType":"bytes","name":"lzArgs_","type":"bytes"}],"name":"crossChainLeverage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"swapAmountOut_","type":"uint256"}],"name":"crossChainLeverageCallback","outputs":[{"internalType":"uint256","name":"_deposited","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"crossChainLeverages","outputs":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"contract IERC20","name":"bridgeToken","type":"address"},{"internalType":"contract IDepositToken","name":"depositToken","type":"address"},{"internalType":"contract ISyntheticToken","name":"syntheticToken","type":"address"},{"internalType":"uint256","name":"bridgeTokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"debtAmount","type":"uint256"},{"internalType":"uint256","name":"depositAmountMin","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"finished","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crossChainRequestsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISyntheticToken","name":"syntheticToken_","type":"address"},{"internalType":"contract IDepositToken","name":"depositToken_","type":"address"},{"internalType":"uint256","name":"withdrawAmount_","type":"uint256"},{"internalType":"uint256","name":"repayAmountMin_","type":"uint256"}],"name":"flashRepay","outputs":[{"internalType":"uint256","name":"_withdrawn","type":"uint256"},{"internalType":"uint256","name":"_repaid","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"_governor","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IPool","name":"pool_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenIn_","type":"address"},{"internalType":"contract IDepositToken","name":"depositToken_","type":"address"},{"internalType":"contract ISyntheticToken","name":"syntheticToken_","type":"address"},{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"leverage_","type":"uint256"},{"internalType":"uint256","name":"depositAmountMin_","type":"uint256"}],"name":"leverage","outputs":[{"internalType":"uint256","name":"_deposited","type":"uint256"},{"internalType":"uint256","name":"_issued","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"payload_","type":"bytes"},{"internalType":"uint256","name":"newRepayAmountMin_","type":"uint256"}],"name":"retryCrossChainFlashRepayCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"address","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"payload_","type":"bytes"},{"internalType":"uint256","name":"newDepositAmountMin_","type":"uint256"}],"name":"retryCrossChainLeverageCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapper","outputs":[{"internalType":"contract ISwapper","name":"_swapper","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b62000152565b6200002e60ff62000031565b50565b60008054610100900460ff1615620000ca578160ff1660011480156200006a575062000068306200014360201b620029f01760201c565b155b620000c25760405162461bcd60e51b815260206004820152602e60248201526000805160206200458983398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff808416911610620001295760405162461bcd60e51b815260206004820152602e60248201526000805160206200458983398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000b9565b506000805460ff191660ff92909216919091179055600190565b6001600160a01b03163b151590565b61442780620001626000396000f3fe6080604052600436106100fe5760003560e01c8063583bfe761161009557806399e5e6551161006457806399e5e6551461034e5780639b6623d8146103e9578063c3557691146103ff578063c4d66de814610412578063ffa1ad741461043257600080fd5b8063583bfe76146102095780636455bf6f146102295780638056777414610257578063823185611461027757600080fd5b8063364fda00116100d1578063364fda001461017f57806339c9a98e146101b45780633bb1f3d0146101c95780634d7e9a76146101e957600080fd5b80630c340a241461010357806316f0115b146101355780632b3297f91461015557806332c615b41461016a575b600080fd5b34801561010f57600080fd5b50610118610470565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561014157600080fd5b50600254610118906001600160a01b031681565b34801561016157600080fd5b506101186104f2565b34801561017657600080fd5b506101186105a7565b34801561018b57600080fd5b5061019f61019a3660046139d6565b61065c565b6040805192835260208301919091520161012c565b6101c76101c2366004613a65565b610c8a565b005b3480156101d557600080fd5b506101c76101e4366004613b30565b611052565b3480156101f557600080fd5b5061019f610204366004613bd8565b61133f565b34801561021557600080fd5b506101c7610224366004613c3d565b6119d3565b34801561023557600080fd5b50610249610244366004613cfa565b611d37565b60405190815260200161012c565b34801561026357600080fd5b50610249610272366004613cfa565b612071565b34801561028357600080fd5b506102f4610292366004613d1c565b603560205260009081526040902080546001820154600283015460038401546004850154600586015460069096015461ffff861696620100009096046001600160a01b039081169695811695948116949190811690600160a01b900460ff1689565b6040805161ffff909a168a526001600160a01b0398891660208b0152968816968901969096529386166060880152608087019290925260a086015260c08501529190911660e083015215156101008201526101200161012c565b34801561035a57600080fd5b506103af610369366004613d1c565b60366020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b03908116929190811690600160a01b900460ff1685565b6040805161ffff90961686526001600160a01b0394851660208701528501929092529190911660608301521515608082015260a00161012c565b3480156103f557600080fd5b5061024960345481565b6101c761040d366004613d35565b612592565b34801561041e57600080fd5b506101c761042d366004613db7565b61294a565b34801561043e57600080fd5b50610463604051806040016040528060058152602001640312e332e360dc1b81525081565b60405161012c9190613e2c565b6002546040805163030d028960e21b815290516000926001600160a01b031691630c340a24916004808301926020929190829003018186803b1580156104b557600080fd5b505afa1580156104c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ed9190613e3f565b905090565b6002546040805163afcff50f60e01b815290516000926001600160a01b03169163afcff50f916004808301926020929190829003018186803b15801561053757600080fd5b505afa15801561054b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056f9190613e3f565b6001600160a01b0316632b3297f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156104b557600080fd5b6002546040805163afcff50f60e01b815290516000926001600160a01b03169163afcff50f916004808301926020929190829003018186803b1580156105ec57600080fd5b505afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190613e3f565b6001600160a01b03166332c615b46040518163ffffffff1660e01b815260040160206040518083038186803b1580156104b557600080fd5b600080600260009054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156106ad57600080fd5b505afa1580156106c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e59190613e6c565b1561070357604051631b0e923f60e11b815260040160405180910390fd5b6002600154141561072f5760405162461bcd60e51b815260040161072690613e87565b60405180910390fd5b6002600181905554604051633e25dee160e21b81526001600160a01b0380881660048301528792169063f8977b849060240160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190613e6c565b6107ce5760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808a16600483015289921690631a0dd00b9060240160206040518083038186803b15801561081357600080fd5b505afa158015610827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084b9190613e6c565b6108685760405163a596698b60e01b815260040160405180910390fd5b85610886576040516310eb483f60e21b815260040160405180910390fd5b6040516370a0823160e01b81523360048201526001600160a01b038816906370a082319060240160206040518083038186803b1580156108c557600080fd5b505afa1580156108d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fd9190613ebe565b86111561091d57604051635de1e54160e01b815260040160405180910390fd5b6002546040516313f1e1f560e31b81526001600160a01b038a81166004830152909116906000908290639f8f0fa89060240160206040518083038186803b15801561096757600080fd5b505afa15801561097b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f9190613e3f565b6040516370a0823160e01b81523360048201529091506001600160a01b038216906370a082319060240160206040518083038186803b1580156109e157600080fd5b505afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a199190613ebe565b871115610a3957604051635de1e54160e01b815260040160405180910390fd5b6040516336e1668760e11b81526001600160a01b038a1690636dc2cd0e90610a679033908c90600401613ed7565b6040805180830381600087803b158015610a8057600080fd5b505af1158015610a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab89190613ef0565b5095506000610ada610ac86104f2565b610ad18c6129ff565b8d8a6000612a78565b604051630450cfaf60e31b81529091506001600160a01b038316906322867d7890610b0b9033908590600401613ed7565b6040805180830381600087803b158015610b2457600080fd5b505af1158015610b38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5c9190613ef0565b50955087861015610b8057604051634394bddf60e11b815260040160405180910390fd5b60405163dde3ab9560e01b81523360048201526000906001600160a01b0385169063dde3ab959060240160a06040518083038186803b158015610bc257600080fd5b505afa158015610bd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfa9190613f14565b50505050905080610c1e5760405163cfd3600360e01b815260040160405180910390fd5b8a6001600160a01b03168c6001600160a01b03167f70e2337c0939e469d0c3d069c581bc0b72c541a70c592cdd46087d24e5e980d28a8a604051610c6c929190918252602082015260400190565b60405180910390a35050505050506001808190555094509492505050565b60026001541415610cad5760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808b1660048301528a92169063f8977b849060240160206040518083038186803b158015610cf757600080fd5b505afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190613e6c565b610d4c5760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808b1660048301528a921690631a0dd00b9060240160206040518083038186803b158015610d9157600080fd5b505afa158015610da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc99190613e6c565b610de65760405163a596698b60e01b815260040160405180910390fd5b8a88610e05576040516310eb483f60e21b815260040160405180910390fd5b670de0b6b3a76400008811610e2d57604051631907e1ff60e21b815260040160405180910390fd5b610ec28b6001600160a01b031663df011c416040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6957600080fd5b505afa158015610e7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea19190613ebe565b610eb390670de0b6b3a7640000613f71565b670de0b6b3a764000090612a92565b881115610ee257604051630a4f5a0760e01b815260040160405180910390fd5b6001600160a01b038116610f0957604051634f70ad6b60e01b815260040160405180910390fd5b600080610f1783338d612acd565b9a50610f25838d8d8d612bec565b6002546040516313f1e1f560e31b81526001600160a01b038f81166004830152929450911690639f8f0fa89060240160206040518083038186803b158015610f6c57600080fd5b505afa158015610f80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa49190613e3f565b6001600160a01b031663bfa17656610fba6105a7565b846040518363ffffffff1660e01b8152600401610fd8929190613ed7565b6040805180830381600087803b158015610ff157600080fd5b505af1158015611005573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110299190613ef0565b50905061103e8d8c848f87868f8f8f8f612d1a565b505060018055505050505050505050505050565b600061109384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612faf92505050565b600081815260366020908152604091829020825160a081018452815461ffff811682526201000090046001600160a01b03908116938201939093526001820154938101939093526002015490811660608301819052600160a01b90910460ff1615156080830152919450925015159050611120576040516311bf899560e21b815260040160405180910390fd5b80606001516001600160a01b0316336001600160a01b031614611156576040516387ab7e7760e01b815260040160405180910390fd5b80608001511561117957604051630814de4560e11b815260040160405180910390fd5b60008281526036602052604081206001018490556111956105a7565b60405163dfda255f60e01b815261ffff8d1660048201529091506000906001600160a01b0383169063dfda255f9060240160206040518083038186803b1580156111de57600080fd5b505afa1580156111f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112169190613e3f565b60405160200161123e919060609190911b6bffffffffffffffffffffffff1916815260140190565b604051602081830303815290604052905082602001516001600160a01b0316636d1bb8f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561128c57600080fd5b505afa1580156112a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c49190613e3f565b6001600160a01b031663cfd6528e8d8d8d8d86888f8f8f6040518a63ffffffff1660e01b81526004016112ff99989796959493929190613fb1565b600060405180830381600087803b15801561131957600080fd5b505af115801561132d573d6000803e3d6000fd5b50505050505050505050505050505050565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b815260040160206040518083038186803b15801561139057600080fd5b505afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c89190613e6c565b156113e657604051631b0e923f60e11b815260040160405180910390fd5b600260015414156114095760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808a1660048301528992169063f8977b849060240160206040518083038186803b15801561145357600080fd5b505afa158015611467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148b9190613e6c565b6114a85760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808a16600483015289921690631a0dd00b9060240160206040518083038186803b1580156114ed57600080fd5b505afa158015611501573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115259190613e6c565b6115425760405163a596698b60e01b815260040160405180910390fd5b86611560576040516310eb483f60e21b815260040160405180910390fd5b670de0b6b3a7640000861161158857604051631907e1ff60e21b815260040160405180910390fd5b6115c4896001600160a01b031663df011c416040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6957600080fd5b8611156115e457604051630a4f5a0760e01b815260040160405180910390fd5b60006115ee6104f2565b905060006115fb8b6129ff565b90506001600160a01b038c1661160f57809b505b61161a8c338b612acd565b9850806001600160a01b03168c6001600160a01b03161461164657611643828d838c6000612a78565b98505b6000611654828c8c8c612bec565b6002546040516313f1e1f560e31b81526001600160a01b038e8116600483015292935060009290911690639f8f0fa89060240160206040518083038186803b15801561169f57600080fd5b505afa1580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d79190613e3f565b604051635fd0bb2b60e11b81529091506001600160a01b0382169063bfa17656906117089030908690600401613ed7565b6040805180830381600087803b15801561172157600080fd5b505af1158015611735573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117599190613ef0565b506040516340c10f1960e01b81529097506001600160a01b038216906340c10f199061178b9033908690600401613ed7565b600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b50505050505060006117cf838c84896000612a78565b6117d9908b61402c565b9050878110156117fc5760405163c724afdf60e01b815260040160405180910390fd5b6118116001600160a01b0383168d6000612fee565b6118256001600160a01b0383168d83612fee565b604051636e553f6560e01b8152600481018290523360248201526001600160a01b038d1690636e553f65906044016040805180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a49190613ef0565b5060025460405163dde3ab9560e01b81523360048201529198506000916001600160a01b039091169063dde3ab959060240160a06040518083038186803b1580156118ee57600080fd5b505afa158015611902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119269190613f14565b5050505090508061194a5760405163cfd3600360e01b815260040160405180910390fd5b8b6001600160a01b03168d6001600160a01b03168f6001600160a01b03167fd82c156e929db20771fc8413cc0789925f6c666a3e5076d5844765ee28bb3a958d8f8c8e6040516119b3949392919093845260208401929092526040830152606082015260800190565b60405180910390a450505050505060018081905550965096945050505050565b6000611a1484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061313d92505050565b600081815260356020908152604091829020825161012081018452815461ffff811682526201000090046001600160a01b0390811693820193909352600182015483169381019390935260028101548216606084015260038101546080840152600481015460a0840152600581015460c08401526006015490811660e08301819052600160a01b90910460ff1615156101008301529193509150611acb576040516311bf899560e21b815260040160405180910390fd5b8060e001516001600160a01b0316336001600160a01b031614611b01576040516387ab7e7760e01b815260040160405180910390fd5b80610100015115611b2557604051630814de4560e11b815260040160405180910390fd5b6000828152603560205260408120600501849055611b416105a7565b60405163dfda255f60e01b815261ffff8e1660048201529091506000906001600160a01b0383169063dfda255f9060240160206040518083038186803b158015611b8a57600080fd5b505afa158015611b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc29190613e3f565b6040516bffffffffffffffffffffffff19606083901b16602082015290915060009063ab8236f360e01b908f9060340160408051601f1981840301815290829052611c1a92918f908f908f908f908f90602401614044565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050826001600160a01b0316633352b6086040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8857600080fd5b505afa158015611c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc09190613e3f565b6001600160a01b031663c0e6ac6c8f8f8f8f88876040518763ffffffff1660e01b8152600401611cf5969594939291906140a8565b600060405180830381600087803b158015611d0f57600080fd5b505af1158015611d23573d6000803e3d6000fd5b505050505050505050505050505050505050565b6002546040805163ecf3a3f960e01b815290516000926001600160a01b03169163ecf3a3f9916004808301926020929190829003018186803b158015611d7c57600080fd5b505afa158015611d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db49190613e6c565b15611dd257604051631b0e923f60e11b815260040160405180910390fd5b60026001541415611df55760405162461bcd60e51b815260040161072690613e87565b6002600155611e026105a7565b6001600160a01b0316336001600160a01b031614611e3357604051632b78ce1b60e11b815260040160405180910390fd5b600083815260366020908152604091829020825160a081018452815461ffff811682526201000090046001600160a01b03908116938201939093526001820154938101939093526002015490811660608301819052600160a01b90910460ff1615156080830152611eb7576040516311bf899560e21b815260040160405180910390fd5b806080015115611eda57604051630814de4560e11b815260040160405180910390fd5b6000848152603660209081526040909120600201805460ff60a01b1916600160a01b179055810151611f0d903385612acd565b60025460208301516040516313f1e1f560e31b81526001600160a01b0391821660048201529295501690639f8f0fa89060240160206040518083038186803b158015611f5857600080fd5b505afa158015611f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f909190613e3f565b6001600160a01b03166322867d788260600151856040518363ffffffff1660e01b8152600401611fc1929190613ed7565b6040805180830381600087803b158015611fda57600080fd5b505af1158015611fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120129190613ef0565b50604082015190925082101561203b57604051634394bddf60e11b815260040160405180910390fd5b60405184907f46da7fdc7ceed834de258df19d8f9ebd7082810a4eb45732d1401df31e5aaa1390600090a2506001805592915050565b6002546040805163ecf3a3f960e01b815290516000926001600160a01b03169163ecf3a3f9916004808301926020929190829003018186803b1580156120b657600080fd5b505afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee9190613e6c565b1561210c57604051631b0e923f60e11b815260040160405180910390fd5b6002600154141561212f5760405162461bcd60e51b815260040161072690613e87565b600260015561213c6105a7565b6001600160a01b0316336001600160a01b03161461216d57604051632b78ce1b60e11b815260040160405180910390fd5b600083815260356020908152604091829020825161012081018452815461ffff811682526201000090046001600160a01b0390811693820193909352600182015483169381019390935260028101548216606084015260038101546080840152600481015460a0840152600581015460c08401526006015490811660e08301819052600160a01b90910460ff16151561010083015261221f576040516311bf899560e21b815260040160405180910390fd5b8061010001511561224357604051630814de4560e11b815260040160405180910390fd5b600061225282604001516129ff565b6000868152603560209081526040909120600601805460ff60a01b1916600160a01b179055830151909150612288903386612acd565b9350600084836080015161229c919061402c565b90506000826001600160a01b031684602001516001600160a01b0316146122db576122d66122c86104f2565b856020015185856000612a78565b6122dd565b815b90508360c001518110156123045760405163c724afdf60e01b815260040160405180910390fd5b604084015161231f906001600160a01b038516906000612fee565b6040840151612339906001600160a01b0385169083612fee565b60408085015160e08601519151636e553f6560e01b8152600481018490526001600160a01b039283166024820152911690636e553f65906044016040805180830381600087803b15801561238c57600080fd5b505af11580156123a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c49190613ef0565b5060025460608601516040516313f1e1f560e31b81526001600160a01b03918216600482015292975016908190639f8f0fa89060240160206040518083038186803b15801561241257600080fd5b505afa158015612426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244a9190613e3f565b6001600160a01b03166340c10f198660e001518760a001516040518363ffffffff1660e01b815260040161247f929190613ed7565b600060405180830381600087803b15801561249957600080fd5b505af11580156124ad573d6000803e3d6000fd5b5050505060e085015160405163dde3ab9560e01b81526001600160a01b03918216600482015260009183169063dde3ab959060240160a06040518083038186803b1580156124fa57600080fd5b505afa15801561250e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125329190613f14565b505050509050806125565760405163cfd3600360e01b815260040160405180910390fd5b60405189907f8e4ff8e32fb3b90b184bdac5bf0d9b2a0fe19baa9dfea95c0fcd7d8e3842e80e90600090a2505060018055509295945050505050565b600260015414156125b55760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808b1660048301528a92169063f8977b849060240160206040518083038186803b1580156125ff57600080fd5b505afa158015612613573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126379190613e6c565b6126545760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808d1660048301528c921690631a0dd00b9060240160206040518083038186803b15801561269957600080fd5b505afa1580156126ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d19190613e6c565b6126ee5760405163a596698b60e01b815260040160405180910390fd5b8861270c576040516310eb483f60e21b815260040160405180910390fd5b6002546040516313f1e1f560e31b81526001600160a01b038d811660048301526000928392911690639f8f0fa89060240160206040518083038186803b15801561275557600080fd5b505afa158015612769573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278d9190613e3f565b9050806001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156127ca57600080fd5b505af11580156127de573d6000803e3d6000fd5b50506040516370a0823160e01b81523360048201526001600160a01b03841692506370a08231915060240160206040518083038186803b15801561282157600080fd5b505afa158015612835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128599190613ebe565b87111561287957604051635de1e54160e01b815260040160405180910390fd5b6128816105a7565b91505060008b6001600160a01b0316639470b0bd338d6040518363ffffffff1660e01b81526004016128b4929190613ed7565b6040805180830381600087803b1580156128cd57600080fd5b505af11580156128e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129059190613ef0565b5090506129256129136104f2565b61291c8e6129ff565b8c848d87613176565b9050612937828b8f848c8c8c8c613392565b5050600180555050505050505050505050565b6000612956600161351b565b9050801561296e576000805461ff0019166101001790555b6001600160a01b03821661299557604051633cb1fb1f60e11b815260040160405180910390fd5b61299d6135a8565b6129a6826135d9565b80156129ec576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b6000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3a57600080fd5b505afa158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a729190613e3f565b92915050565b6000612a88868686868630613176565b9695505050505050565b600081612aa0600282614104565b612ab2670de0b6b3a764000086614126565b612abc919061402c565b612ac69190614104565b9392505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a082319060240160206040518083038186803b158015612b1157600080fd5b505afa158015612b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b499190613ebe565b9050612b606001600160a01b038616853086613649565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a082319060240160206040518083038186803b158015612ba157600080fd5b505afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd99190613ebe565b612be39190613f71565b95945050505050565b60025460408051637556d1c160e11b815290516000926001600160a01b03169163eaada382916004808301926020929190829003018186803b158015612c3157600080fd5b505afa158015612c45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c699190613e3f565b6001600160a01b031663b64663848686612c9587612c8f670de0b6b3a764000089613f71565b90613687565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152604482015260640160206040518083038186803b158015612ce257600080fd5b505afa158015612cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be39190613ebe565b6000612d246136bf565b90506000612d6784848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370692505050565b505090506040518061012001604052808261ffff168152602001896001600160a01b031681526020018d6001600160a01b031681526020018a6001600160a01b031681526020018c81526020018b8152602001868152602001336001600160a01b03168152602001600015158152506035600084815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160020160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506080820151816003015560a0820151816004015560c0820151816005015560e08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160060160146101000a81548160ff02191690831515021790555090505050612f0b6105a7565b6001600160a01b03166339f648bf3483338c8c8c8c8b8b6040518a63ffffffff1660e01b8152600401612f45989796959493929190614145565b6000604051808303818588803b158015612f5e57600080fd5b505af1158015612f72573d6000803e3d6000fd5b50506040518493507f46a791deaa2c43990d6e3b60a320fbebef9a6677379f326b308fb9efc8128619925060009150a25050505050505050505050565b600080600083806020019051810190612fc891906141a4565b8051909550612fe191508501602090810190860161426d565b9250925092509193909250565b8015806130775750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561303d57600080fd5b505afa158015613051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130759190613ebe565b155b6130e25760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610726565b6131388363095ea7b360e01b8484604051602401613101929190613ed7565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261371f565b505050565b6000808280602001905181019061315491906141a4565b805190945061316d9150840160209081019085016142b0565b91509150915091565b6000846001600160a01b0316866001600160a01b031614613363576131a66001600160a01b038716886000612fee565b6131ba6001600160a01b0387168886612fee565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908716906370a082319060240160206040518083038186803b1580156131ff57600080fd5b505afa158015613213573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132379190613ebe565b604051636ccb2b0160e01b81526001600160a01b03898116600483015288811660248301526044820188905260648201879052858116608483015291925090891690636ccb2b019060a401602060405180830381600087803b15801561329c57600080fd5b505af11580156132b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d49190613ebe565b506040516370a0823160e01b81526001600160a01b0384811660048301528291908816906370a082319060240160206040518083038186803b15801561331957600080fd5b505afa15801561332d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133519190613ebe565b61335b9190613f71565b915050612a88565b6001600160a01b0382163014613387576133876001600160a01b03871683866137f1565b509195945050505050565b600061339c6136bf565b905060006133df84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370692505050565b50506040805160a08101825261ffff80841682526001600160a01b03808d1660208085019182528486018c815233606087018181526000608089018181528d82526036909552899020975188549551871662010000026001600160b01b031990961697169690961793909317865551600186015592516002909401805493511515600160a01b026001600160a81b03199094169483169490941792909217909255915162bc9db960e01b81529293508c169162bc9db99134916134b29187918f908f908f908f908e908e90600401614145565b6000604051808303818588803b1580156134cb57600080fd5b505af11580156134df573d6000803e3d6000fd5b50506040518593507ff83a8331f3e68a894879f051738cb73cdced1709a214e49f6dc1d541a0415e8b925060009150a250505050505050505050565b60008054610100900460ff1615613562578160ff16600114801561353e5750303b155b61355a5760405162461bcd60e51b8152600401610726906142de565b506000919050565b60005460ff8084169116106135895760405162461bcd60e51b8152600401610726906142de565b506000805460ff191660ff92909216919091179055600190565b919050565b600054610100900460ff166135cf5760405162461bcd60e51b81526004016107269061432c565b6135d7613810565b565b600054610100900460ff166136005760405162461bcd60e51b81526004016107269061432c565b6001600160a01b0381166136275760405163724f500960e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040516001600160a01b03808516602483015283166044820152606481018290526136819085906323b872dd60e01b90608401613101565b50505050565b6000821580613694575081155b156136a157506000612a72565b670de0b6b3a76400006136b5600282614104565b612ab28486614126565b6000466034600081546136d190614377565b91829055506040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905090565b600080600083806020019051810190612fe19190614392565b6000613774826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661383d9092919063ffffffff16565b80519091501561313857808060200190518101906137929190613e6c565b6131385760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610726565b6131388363a9059cbb60e01b8484604051602401613101929190613ed7565b600054610100900460ff166138375760405162461bcd60e51b81526004016107269061432c565b60018055565b606061384c8484600085613854565b949350505050565b6060824710156138b55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610726565b6001600160a01b0385163b61390c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610726565b600080866001600160a01b0316858760405161392891906143d5565b60006040518083038185875af1925050503d8060008114613965576040519150601f19603f3d011682016040523d82523d6000602084013e61396a565b606091505b509150915061397a828286613985565b979650505050505050565b60608315613994575081612ac6565b8251156139a45782518084602001fd5b8160405162461bcd60e51b81526004016107269190613e2c565b6001600160a01b03811681146139d357600080fd5b50565b600080600080608085870312156139ec57600080fd5b84356139f7816139be565b93506020850135613a07816139be565b93969395505050506040820135916060013590565b60008083601f840112613a2e57600080fd5b50813567ffffffffffffffff811115613a4657600080fd5b602083019150836020828501011115613a5e57600080fd5b9250929050565b60008060008060008060008060006101008a8c031215613a8457600080fd5b8935613a8f816139be565b985060208a0135613a9f816139be565b975060408a0135613aaf816139be565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff811115613ae757600080fd5b613af38c828d01613a1c565b915080935050809150509295985092959850929598565b61ffff811681146139d357600080fd5b67ffffffffffffffff811681146139d357600080fd5b60008060008060008060008060c0898b031215613b4c57600080fd5b8835613b5781613b0a565b9750602089013567ffffffffffffffff80821115613b7457600080fd5b613b808c838d01613a1c565b909950975060408b01359150613b9582613b1a565b90955060608a0135945060808a01359080821115613bb257600080fd5b50613bbf8b828c01613a1c565b999c989b50969995989497949560a00135949350505050565b60008060008060008060c08789031215613bf157600080fd5b8635613bfc816139be565b95506020870135613c0c816139be565b94506040870135613c1c816139be565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600080600080600060e08a8c031215613c5b57600080fd5b8935613c6681613b0a565b985060208a013567ffffffffffffffff80821115613c8357600080fd5b613c8f8d838e01613a1c565b909a50985060408c01359150613ca482613b1a565b90965060608b013590613cb6826139be565b90955060808b0135945060a08b01359080821115613cd357600080fd5b50613ce08c828d01613a1c565b9a9d999c50979a9699959894979660c00135949350505050565b60008060408385031215613d0d57600080fd5b50508035926020909101359150565b600060208284031215613d2e57600080fd5b5035919050565b60008060008060008060008060006101008a8c031215613d5457600080fd5b8935613d5f816139be565b985060208a0135613d6f816139be565b975060408a0135965060608a0135613d86816139be565b955060808a0135945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff811115613ae757600080fd5b600060208284031215613dc957600080fd5b8135612ac6816139be565b60005b83811015613def578181015183820152602001613dd7565b838111156136815750506000910152565b60008151808452613e18816020860160208601613dd4565b601f01601f19169290920160200192915050565b602081526000612ac66020830184613e00565b600060208284031215613e5157600080fd5b8151612ac6816139be565b805180151581146135a357600080fd5b600060208284031215613e7e57600080fd5b612ac682613e5c565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215613ed057600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b60008060408385031215613f0357600080fd5b505080516020909101519092909150565b600080600080600060a08688031215613f2c57600080fd5b613f3586613e5c565b602087015160408801516060890151608090990151929a91995097965090945092505050565b634e487b7160e01b600052601160045260246000fd5b600082821015613f8357613f83613f5b565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff8a16815260e060208201526000613fcf60e083018a8c613f88565b67ffffffffffffffff891660408401528281036060840152613ff18189613e00565b6001600160a01b038816608085015260a0840187905283810360c0850152905061401c818587613f88565b9c9b505050505050505050505050565b6000821982111561403f5761403f613f5b565b500190565b61ffff8816815260c06020820152600061406160c0830189613e00565b67ffffffffffffffff881660408401526001600160a01b03871660608401526080830186905282810360a084015261409a818587613f88565b9a9950505050505050505050565b61ffff8716815260a0602082015260006140c660a083018789613f88565b67ffffffffffffffff861660408401526001600160a01b038516606084015282810360808401526140f78185613e00565b9998505050505050505050565b60008261412157634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561414057614140613f5b565b500290565b8881526001600160a01b0388811660208301528781166040830152861660608201526080810185905260a0810184905260e060c0820181905260009061409a9083018486613f88565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156141b757600080fd5b825160ff811681146141c857600080fd5b602084015190925067ffffffffffffffff808211156141e657600080fd5b818501915085601f8301126141fa57600080fd5b81518181111561420c5761420c61418e565b604051601f8201601f19908116603f011681019083821181831017156142345761423461418e565b8160405282815288602084870101111561424d57600080fd5b61425e836020830160208801613dd4565b80955050505050509250929050565b60008060006060848603121561428257600080fd5b835161428d816139be565b602085015190935061429e816139be565b80925050604084015190509250925092565b600080604083850312156142c357600080fd5b82516142ce816139be565b6020939093015192949293505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060001982141561438b5761438b613f5b565b5060010190565b6000806000606084860312156143a757600080fd5b83516143b281613b0a565b6020850151604086015191945092506143ca81613b1a565b809150509250925092565b600082516143e7818460208701613dd4565b919091019291505056fea2646970667358221220542011671db719c2bf3af890e7b7f90cc6b40a01b9d31e3b267472d3668c7eb764736f6c63430008090033496e697469616c697a61626c653a20636f6e747261637420697320616c726561
Deployed Bytecode
0x6080604052600436106100fe5760003560e01c8063583bfe761161009557806399e5e6551161006457806399e5e6551461034e5780639b6623d8146103e9578063c3557691146103ff578063c4d66de814610412578063ffa1ad741461043257600080fd5b8063583bfe76146102095780636455bf6f146102295780638056777414610257578063823185611461027757600080fd5b8063364fda00116100d1578063364fda001461017f57806339c9a98e146101b45780633bb1f3d0146101c95780634d7e9a76146101e957600080fd5b80630c340a241461010357806316f0115b146101355780632b3297f91461015557806332c615b41461016a575b600080fd5b34801561010f57600080fd5b50610118610470565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561014157600080fd5b50600254610118906001600160a01b031681565b34801561016157600080fd5b506101186104f2565b34801561017657600080fd5b506101186105a7565b34801561018b57600080fd5b5061019f61019a3660046139d6565b61065c565b6040805192835260208301919091520161012c565b6101c76101c2366004613a65565b610c8a565b005b3480156101d557600080fd5b506101c76101e4366004613b30565b611052565b3480156101f557600080fd5b5061019f610204366004613bd8565b61133f565b34801561021557600080fd5b506101c7610224366004613c3d565b6119d3565b34801561023557600080fd5b50610249610244366004613cfa565b611d37565b60405190815260200161012c565b34801561026357600080fd5b50610249610272366004613cfa565b612071565b34801561028357600080fd5b506102f4610292366004613d1c565b603560205260009081526040902080546001820154600283015460038401546004850154600586015460069096015461ffff861696620100009096046001600160a01b039081169695811695948116949190811690600160a01b900460ff1689565b6040805161ffff909a168a526001600160a01b0398891660208b0152968816968901969096529386166060880152608087019290925260a086015260c08501529190911660e083015215156101008201526101200161012c565b34801561035a57600080fd5b506103af610369366004613d1c565b60366020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b03908116929190811690600160a01b900460ff1685565b6040805161ffff90961686526001600160a01b0394851660208701528501929092529190911660608301521515608082015260a00161012c565b3480156103f557600080fd5b5061024960345481565b6101c761040d366004613d35565b612592565b34801561041e57600080fd5b506101c761042d366004613db7565b61294a565b34801561043e57600080fd5b50610463604051806040016040528060058152602001640312e332e360dc1b81525081565b60405161012c9190613e2c565b6002546040805163030d028960e21b815290516000926001600160a01b031691630c340a24916004808301926020929190829003018186803b1580156104b557600080fd5b505afa1580156104c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ed9190613e3f565b905090565b6002546040805163afcff50f60e01b815290516000926001600160a01b03169163afcff50f916004808301926020929190829003018186803b15801561053757600080fd5b505afa15801561054b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056f9190613e3f565b6001600160a01b0316632b3297f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156104b557600080fd5b6002546040805163afcff50f60e01b815290516000926001600160a01b03169163afcff50f916004808301926020929190829003018186803b1580156105ec57600080fd5b505afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190613e3f565b6001600160a01b03166332c615b46040518163ffffffff1660e01b815260040160206040518083038186803b1580156104b557600080fd5b600080600260009054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156106ad57600080fd5b505afa1580156106c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e59190613e6c565b1561070357604051631b0e923f60e11b815260040160405180910390fd5b6002600154141561072f5760405162461bcd60e51b815260040161072690613e87565b60405180910390fd5b6002600181905554604051633e25dee160e21b81526001600160a01b0380881660048301528792169063f8977b849060240160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190613e6c565b6107ce5760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808a16600483015289921690631a0dd00b9060240160206040518083038186803b15801561081357600080fd5b505afa158015610827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084b9190613e6c565b6108685760405163a596698b60e01b815260040160405180910390fd5b85610886576040516310eb483f60e21b815260040160405180910390fd5b6040516370a0823160e01b81523360048201526001600160a01b038816906370a082319060240160206040518083038186803b1580156108c557600080fd5b505afa1580156108d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108fd9190613ebe565b86111561091d57604051635de1e54160e01b815260040160405180910390fd5b6002546040516313f1e1f560e31b81526001600160a01b038a81166004830152909116906000908290639f8f0fa89060240160206040518083038186803b15801561096757600080fd5b505afa15801561097b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f9190613e3f565b6040516370a0823160e01b81523360048201529091506001600160a01b038216906370a082319060240160206040518083038186803b1580156109e157600080fd5b505afa1580156109f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a199190613ebe565b871115610a3957604051635de1e54160e01b815260040160405180910390fd5b6040516336e1668760e11b81526001600160a01b038a1690636dc2cd0e90610a679033908c90600401613ed7565b6040805180830381600087803b158015610a8057600080fd5b505af1158015610a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab89190613ef0565b5095506000610ada610ac86104f2565b610ad18c6129ff565b8d8a6000612a78565b604051630450cfaf60e31b81529091506001600160a01b038316906322867d7890610b0b9033908590600401613ed7565b6040805180830381600087803b158015610b2457600080fd5b505af1158015610b38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5c9190613ef0565b50955087861015610b8057604051634394bddf60e11b815260040160405180910390fd5b60405163dde3ab9560e01b81523360048201526000906001600160a01b0385169063dde3ab959060240160a06040518083038186803b158015610bc257600080fd5b505afa158015610bd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfa9190613f14565b50505050905080610c1e5760405163cfd3600360e01b815260040160405180910390fd5b8a6001600160a01b03168c6001600160a01b03167f70e2337c0939e469d0c3d069c581bc0b72c541a70c592cdd46087d24e5e980d28a8a604051610c6c929190918252602082015260400190565b60405180910390a35050505050506001808190555094509492505050565b60026001541415610cad5760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808b1660048301528a92169063f8977b849060240160206040518083038186803b158015610cf757600080fd5b505afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2f9190613e6c565b610d4c5760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808b1660048301528a921690631a0dd00b9060240160206040518083038186803b158015610d9157600080fd5b505afa158015610da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc99190613e6c565b610de65760405163a596698b60e01b815260040160405180910390fd5b8a88610e05576040516310eb483f60e21b815260040160405180910390fd5b670de0b6b3a76400008811610e2d57604051631907e1ff60e21b815260040160405180910390fd5b610ec28b6001600160a01b031663df011c416040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6957600080fd5b505afa158015610e7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea19190613ebe565b610eb390670de0b6b3a7640000613f71565b670de0b6b3a764000090612a92565b881115610ee257604051630a4f5a0760e01b815260040160405180910390fd5b6001600160a01b038116610f0957604051634f70ad6b60e01b815260040160405180910390fd5b600080610f1783338d612acd565b9a50610f25838d8d8d612bec565b6002546040516313f1e1f560e31b81526001600160a01b038f81166004830152929450911690639f8f0fa89060240160206040518083038186803b158015610f6c57600080fd5b505afa158015610f80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa49190613e3f565b6001600160a01b031663bfa17656610fba6105a7565b846040518363ffffffff1660e01b8152600401610fd8929190613ed7565b6040805180830381600087803b158015610ff157600080fd5b505af1158015611005573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110299190613ef0565b50905061103e8d8c848f87868f8f8f8f612d1a565b505060018055505050505050505050505050565b600061109384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612faf92505050565b600081815260366020908152604091829020825160a081018452815461ffff811682526201000090046001600160a01b03908116938201939093526001820154938101939093526002015490811660608301819052600160a01b90910460ff1615156080830152919450925015159050611120576040516311bf899560e21b815260040160405180910390fd5b80606001516001600160a01b0316336001600160a01b031614611156576040516387ab7e7760e01b815260040160405180910390fd5b80608001511561117957604051630814de4560e11b815260040160405180910390fd5b60008281526036602052604081206001018490556111956105a7565b60405163dfda255f60e01b815261ffff8d1660048201529091506000906001600160a01b0383169063dfda255f9060240160206040518083038186803b1580156111de57600080fd5b505afa1580156111f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112169190613e3f565b60405160200161123e919060609190911b6bffffffffffffffffffffffff1916815260140190565b604051602081830303815290604052905082602001516001600160a01b0316636d1bb8f76040518163ffffffff1660e01b815260040160206040518083038186803b15801561128c57600080fd5b505afa1580156112a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c49190613e3f565b6001600160a01b031663cfd6528e8d8d8d8d86888f8f8f6040518a63ffffffff1660e01b81526004016112ff99989796959493929190613fb1565b600060405180830381600087803b15801561131957600080fd5b505af115801561132d573d6000803e3d6000fd5b50505050505050505050505050505050565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b815260040160206040518083038186803b15801561139057600080fd5b505afa1580156113a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c89190613e6c565b156113e657604051631b0e923f60e11b815260040160405180910390fd5b600260015414156114095760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808a1660048301528992169063f8977b849060240160206040518083038186803b15801561145357600080fd5b505afa158015611467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148b9190613e6c565b6114a85760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808a16600483015289921690631a0dd00b9060240160206040518083038186803b1580156114ed57600080fd5b505afa158015611501573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115259190613e6c565b6115425760405163a596698b60e01b815260040160405180910390fd5b86611560576040516310eb483f60e21b815260040160405180910390fd5b670de0b6b3a7640000861161158857604051631907e1ff60e21b815260040160405180910390fd5b6115c4896001600160a01b031663df011c416040518163ffffffff1660e01b815260040160206040518083038186803b158015610e6957600080fd5b8611156115e457604051630a4f5a0760e01b815260040160405180910390fd5b60006115ee6104f2565b905060006115fb8b6129ff565b90506001600160a01b038c1661160f57809b505b61161a8c338b612acd565b9850806001600160a01b03168c6001600160a01b03161461164657611643828d838c6000612a78565b98505b6000611654828c8c8c612bec565b6002546040516313f1e1f560e31b81526001600160a01b038e8116600483015292935060009290911690639f8f0fa89060240160206040518083038186803b15801561169f57600080fd5b505afa1580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d79190613e3f565b604051635fd0bb2b60e11b81529091506001600160a01b0382169063bfa17656906117089030908690600401613ed7565b6040805180830381600087803b15801561172157600080fd5b505af1158015611735573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117599190613ef0565b506040516340c10f1960e01b81529097506001600160a01b038216906340c10f199061178b9033908690600401613ed7565b600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b50505050505060006117cf838c84896000612a78565b6117d9908b61402c565b9050878110156117fc5760405163c724afdf60e01b815260040160405180910390fd5b6118116001600160a01b0383168d6000612fee565b6118256001600160a01b0383168d83612fee565b604051636e553f6560e01b8152600481018290523360248201526001600160a01b038d1690636e553f65906044016040805180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a49190613ef0565b5060025460405163dde3ab9560e01b81523360048201529198506000916001600160a01b039091169063dde3ab959060240160a06040518083038186803b1580156118ee57600080fd5b505afa158015611902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119269190613f14565b5050505090508061194a5760405163cfd3600360e01b815260040160405180910390fd5b8b6001600160a01b03168d6001600160a01b03168f6001600160a01b03167fd82c156e929db20771fc8413cc0789925f6c666a3e5076d5844765ee28bb3a958d8f8c8e6040516119b3949392919093845260208401929092526040830152606082015260800190565b60405180910390a450505050505060018081905550965096945050505050565b6000611a1484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061313d92505050565b600081815260356020908152604091829020825161012081018452815461ffff811682526201000090046001600160a01b0390811693820193909352600182015483169381019390935260028101548216606084015260038101546080840152600481015460a0840152600581015460c08401526006015490811660e08301819052600160a01b90910460ff1615156101008301529193509150611acb576040516311bf899560e21b815260040160405180910390fd5b8060e001516001600160a01b0316336001600160a01b031614611b01576040516387ab7e7760e01b815260040160405180910390fd5b80610100015115611b2557604051630814de4560e11b815260040160405180910390fd5b6000828152603560205260408120600501849055611b416105a7565b60405163dfda255f60e01b815261ffff8e1660048201529091506000906001600160a01b0383169063dfda255f9060240160206040518083038186803b158015611b8a57600080fd5b505afa158015611b9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc29190613e3f565b6040516bffffffffffffffffffffffff19606083901b16602082015290915060009063ab8236f360e01b908f9060340160408051601f1981840301815290829052611c1a92918f908f908f908f908f90602401614044565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050826001600160a01b0316633352b6086040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8857600080fd5b505afa158015611c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc09190613e3f565b6001600160a01b031663c0e6ac6c8f8f8f8f88876040518763ffffffff1660e01b8152600401611cf5969594939291906140a8565b600060405180830381600087803b158015611d0f57600080fd5b505af1158015611d23573d6000803e3d6000fd5b505050505050505050505050505050505050565b6002546040805163ecf3a3f960e01b815290516000926001600160a01b03169163ecf3a3f9916004808301926020929190829003018186803b158015611d7c57600080fd5b505afa158015611d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db49190613e6c565b15611dd257604051631b0e923f60e11b815260040160405180910390fd5b60026001541415611df55760405162461bcd60e51b815260040161072690613e87565b6002600155611e026105a7565b6001600160a01b0316336001600160a01b031614611e3357604051632b78ce1b60e11b815260040160405180910390fd5b600083815260366020908152604091829020825160a081018452815461ffff811682526201000090046001600160a01b03908116938201939093526001820154938101939093526002015490811660608301819052600160a01b90910460ff1615156080830152611eb7576040516311bf899560e21b815260040160405180910390fd5b806080015115611eda57604051630814de4560e11b815260040160405180910390fd5b6000848152603660209081526040909120600201805460ff60a01b1916600160a01b179055810151611f0d903385612acd565b60025460208301516040516313f1e1f560e31b81526001600160a01b0391821660048201529295501690639f8f0fa89060240160206040518083038186803b158015611f5857600080fd5b505afa158015611f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f909190613e3f565b6001600160a01b03166322867d788260600151856040518363ffffffff1660e01b8152600401611fc1929190613ed7565b6040805180830381600087803b158015611fda57600080fd5b505af1158015611fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120129190613ef0565b50604082015190925082101561203b57604051634394bddf60e11b815260040160405180910390fd5b60405184907f46da7fdc7ceed834de258df19d8f9ebd7082810a4eb45732d1401df31e5aaa1390600090a2506001805592915050565b6002546040805163ecf3a3f960e01b815290516000926001600160a01b03169163ecf3a3f9916004808301926020929190829003018186803b1580156120b657600080fd5b505afa1580156120ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ee9190613e6c565b1561210c57604051631b0e923f60e11b815260040160405180910390fd5b6002600154141561212f5760405162461bcd60e51b815260040161072690613e87565b600260015561213c6105a7565b6001600160a01b0316336001600160a01b03161461216d57604051632b78ce1b60e11b815260040160405180910390fd5b600083815260356020908152604091829020825161012081018452815461ffff811682526201000090046001600160a01b0390811693820193909352600182015483169381019390935260028101548216606084015260038101546080840152600481015460a0840152600581015460c08401526006015490811660e08301819052600160a01b90910460ff16151561010083015261221f576040516311bf899560e21b815260040160405180910390fd5b8061010001511561224357604051630814de4560e11b815260040160405180910390fd5b600061225282604001516129ff565b6000868152603560209081526040909120600601805460ff60a01b1916600160a01b179055830151909150612288903386612acd565b9350600084836080015161229c919061402c565b90506000826001600160a01b031684602001516001600160a01b0316146122db576122d66122c86104f2565b856020015185856000612a78565b6122dd565b815b90508360c001518110156123045760405163c724afdf60e01b815260040160405180910390fd5b604084015161231f906001600160a01b038516906000612fee565b6040840151612339906001600160a01b0385169083612fee565b60408085015160e08601519151636e553f6560e01b8152600481018490526001600160a01b039283166024820152911690636e553f65906044016040805180830381600087803b15801561238c57600080fd5b505af11580156123a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c49190613ef0565b5060025460608601516040516313f1e1f560e31b81526001600160a01b03918216600482015292975016908190639f8f0fa89060240160206040518083038186803b15801561241257600080fd5b505afa158015612426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244a9190613e3f565b6001600160a01b03166340c10f198660e001518760a001516040518363ffffffff1660e01b815260040161247f929190613ed7565b600060405180830381600087803b15801561249957600080fd5b505af11580156124ad573d6000803e3d6000fd5b5050505060e085015160405163dde3ab9560e01b81526001600160a01b03918216600482015260009183169063dde3ab959060240160a06040518083038186803b1580156124fa57600080fd5b505afa15801561250e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125329190613f14565b505050509050806125565760405163cfd3600360e01b815260040160405180910390fd5b60405189907f8e4ff8e32fb3b90b184bdac5bf0d9b2a0fe19baa9dfea95c0fcd7d8e3842e80e90600090a2505060018055509295945050505050565b600260015414156125b55760405162461bcd60e51b815260040161072690613e87565b6002600181905554604051633e25dee160e21b81526001600160a01b03808b1660048301528a92169063f8977b849060240160206040518083038186803b1580156125ff57600080fd5b505afa158015612613573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126379190613e6c565b6126545760405163a67d528360e01b815260040160405180910390fd5b600254604051631a0dd00b60e01b81526001600160a01b03808d1660048301528c921690631a0dd00b9060240160206040518083038186803b15801561269957600080fd5b505afa1580156126ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d19190613e6c565b6126ee5760405163a596698b60e01b815260040160405180910390fd5b8861270c576040516310eb483f60e21b815260040160405180910390fd5b6002546040516313f1e1f560e31b81526001600160a01b038d811660048301526000928392911690639f8f0fa89060240160206040518083038186803b15801561275557600080fd5b505afa158015612769573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278d9190613e3f565b9050806001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156127ca57600080fd5b505af11580156127de573d6000803e3d6000fd5b50506040516370a0823160e01b81523360048201526001600160a01b03841692506370a08231915060240160206040518083038186803b15801561282157600080fd5b505afa158015612835573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128599190613ebe565b87111561287957604051635de1e54160e01b815260040160405180910390fd5b6128816105a7565b91505060008b6001600160a01b0316639470b0bd338d6040518363ffffffff1660e01b81526004016128b4929190613ed7565b6040805180830381600087803b1580156128cd57600080fd5b505af11580156128e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129059190613ef0565b5090506129256129136104f2565b61291c8e6129ff565b8c848d87613176565b9050612937828b8f848c8c8c8c613392565b5050600180555050505050505050505050565b6000612956600161351b565b9050801561296e576000805461ff0019166101001790555b6001600160a01b03821661299557604051633cb1fb1f60e11b815260040160405180910390fd5b61299d6135a8565b6129a6826135d9565b80156129ec576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b6000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3a57600080fd5b505afa158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a729190613e3f565b92915050565b6000612a88868686868630613176565b9695505050505050565b600081612aa0600282614104565b612ab2670de0b6b3a764000086614126565b612abc919061402c565b612ac69190614104565b9392505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a082319060240160206040518083038186803b158015612b1157600080fd5b505afa158015612b25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b499190613ebe565b9050612b606001600160a01b038616853086613649565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a082319060240160206040518083038186803b158015612ba157600080fd5b505afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd99190613ebe565b612be39190613f71565b95945050505050565b60025460408051637556d1c160e11b815290516000926001600160a01b03169163eaada382916004808301926020929190829003018186803b158015612c3157600080fd5b505afa158015612c45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c699190613e3f565b6001600160a01b031663b64663848686612c9587612c8f670de0b6b3a764000089613f71565b90613687565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152604482015260640160206040518083038186803b158015612ce257600080fd5b505afa158015612cf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be39190613ebe565b6000612d246136bf565b90506000612d6784848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370692505050565b505090506040518061012001604052808261ffff168152602001896001600160a01b031681526020018d6001600160a01b031681526020018a6001600160a01b031681526020018c81526020018b8152602001868152602001336001600160a01b03168152602001600015158152506035600084815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160020160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506080820151816003015560a0820151816004015560c0820151816005015560e08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160060160146101000a81548160ff02191690831515021790555090505050612f0b6105a7565b6001600160a01b03166339f648bf3483338c8c8c8c8b8b6040518a63ffffffff1660e01b8152600401612f45989796959493929190614145565b6000604051808303818588803b158015612f5e57600080fd5b505af1158015612f72573d6000803e3d6000fd5b50506040518493507f46a791deaa2c43990d6e3b60a320fbebef9a6677379f326b308fb9efc8128619925060009150a25050505050505050505050565b600080600083806020019051810190612fc891906141a4565b8051909550612fe191508501602090810190860161426d565b9250925092509193909250565b8015806130775750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561303d57600080fd5b505afa158015613051573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130759190613ebe565b155b6130e25760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610726565b6131388363095ea7b360e01b8484604051602401613101929190613ed7565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261371f565b505050565b6000808280602001905181019061315491906141a4565b805190945061316d9150840160209081019085016142b0565b91509150915091565b6000846001600160a01b0316866001600160a01b031614613363576131a66001600160a01b038716886000612fee565b6131ba6001600160a01b0387168886612fee565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908716906370a082319060240160206040518083038186803b1580156131ff57600080fd5b505afa158015613213573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132379190613ebe565b604051636ccb2b0160e01b81526001600160a01b03898116600483015288811660248301526044820188905260648201879052858116608483015291925090891690636ccb2b019060a401602060405180830381600087803b15801561329c57600080fd5b505af11580156132b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d49190613ebe565b506040516370a0823160e01b81526001600160a01b0384811660048301528291908816906370a082319060240160206040518083038186803b15801561331957600080fd5b505afa15801561332d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133519190613ebe565b61335b9190613f71565b915050612a88565b6001600160a01b0382163014613387576133876001600160a01b03871683866137f1565b509195945050505050565b600061339c6136bf565b905060006133df84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370692505050565b50506040805160a08101825261ffff80841682526001600160a01b03808d1660208085019182528486018c815233606087018181526000608089018181528d82526036909552899020975188549551871662010000026001600160b01b031990961697169690961793909317865551600186015592516002909401805493511515600160a01b026001600160a81b03199094169483169490941792909217909255915162bc9db960e01b81529293508c169162bc9db99134916134b29187918f908f908f908f908e908e90600401614145565b6000604051808303818588803b1580156134cb57600080fd5b505af11580156134df573d6000803e3d6000fd5b50506040518593507ff83a8331f3e68a894879f051738cb73cdced1709a214e49f6dc1d541a0415e8b925060009150a250505050505050505050565b60008054610100900460ff1615613562578160ff16600114801561353e5750303b155b61355a5760405162461bcd60e51b8152600401610726906142de565b506000919050565b60005460ff8084169116106135895760405162461bcd60e51b8152600401610726906142de565b506000805460ff191660ff92909216919091179055600190565b919050565b600054610100900460ff166135cf5760405162461bcd60e51b81526004016107269061432c565b6135d7613810565b565b600054610100900460ff166136005760405162461bcd60e51b81526004016107269061432c565b6001600160a01b0381166136275760405163724f500960e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6040516001600160a01b03808516602483015283166044820152606481018290526136819085906323b872dd60e01b90608401613101565b50505050565b6000821580613694575081155b156136a157506000612a72565b670de0b6b3a76400006136b5600282614104565b612ab28486614126565b6000466034600081546136d190614377565b91829055506040805160208101939093528201526060016040516020818303038152906040528051906020012060001c905090565b600080600083806020019051810190612fe19190614392565b6000613774826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661383d9092919063ffffffff16565b80519091501561313857808060200190518101906137929190613e6c565b6131385760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610726565b6131388363a9059cbb60e01b8484604051602401613101929190613ed7565b600054610100900460ff166138375760405162461bcd60e51b81526004016107269061432c565b60018055565b606061384c8484600085613854565b949350505050565b6060824710156138b55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610726565b6001600160a01b0385163b61390c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610726565b600080866001600160a01b0316858760405161392891906143d5565b60006040518083038185875af1925050503d8060008114613965576040519150601f19603f3d011682016040523d82523d6000602084013e61396a565b606091505b509150915061397a828286613985565b979650505050505050565b60608315613994575081612ac6565b8251156139a45782518084602001fd5b8160405162461bcd60e51b81526004016107269190613e2c565b6001600160a01b03811681146139d357600080fd5b50565b600080600080608085870312156139ec57600080fd5b84356139f7816139be565b93506020850135613a07816139be565b93969395505050506040820135916060013590565b60008083601f840112613a2e57600080fd5b50813567ffffffffffffffff811115613a4657600080fd5b602083019150836020828501011115613a5e57600080fd5b9250929050565b60008060008060008060008060006101008a8c031215613a8457600080fd5b8935613a8f816139be565b985060208a0135613a9f816139be565b975060408a0135613aaf816139be565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff811115613ae757600080fd5b613af38c828d01613a1c565b915080935050809150509295985092959850929598565b61ffff811681146139d357600080fd5b67ffffffffffffffff811681146139d357600080fd5b60008060008060008060008060c0898b031215613b4c57600080fd5b8835613b5781613b0a565b9750602089013567ffffffffffffffff80821115613b7457600080fd5b613b808c838d01613a1c565b909950975060408b01359150613b9582613b1a565b90955060608a0135945060808a01359080821115613bb257600080fd5b50613bbf8b828c01613a1c565b999c989b50969995989497949560a00135949350505050565b60008060008060008060c08789031215613bf157600080fd5b8635613bfc816139be565b95506020870135613c0c816139be565b94506040870135613c1c816139be565b959894975094956060810135955060808101359460a0909101359350915050565b600080600080600080600080600060e08a8c031215613c5b57600080fd5b8935613c6681613b0a565b985060208a013567ffffffffffffffff80821115613c8357600080fd5b613c8f8d838e01613a1c565b909a50985060408c01359150613ca482613b1a565b90965060608b013590613cb6826139be565b90955060808b0135945060a08b01359080821115613cd357600080fd5b50613ce08c828d01613a1c565b9a9d999c50979a9699959894979660c00135949350505050565b60008060408385031215613d0d57600080fd5b50508035926020909101359150565b600060208284031215613d2e57600080fd5b5035919050565b60008060008060008060008060006101008a8c031215613d5457600080fd5b8935613d5f816139be565b985060208a0135613d6f816139be565b975060408a0135965060608a0135613d86816139be565b955060808a0135945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff811115613ae757600080fd5b600060208284031215613dc957600080fd5b8135612ac6816139be565b60005b83811015613def578181015183820152602001613dd7565b838111156136815750506000910152565b60008151808452613e18816020860160208601613dd4565b601f01601f19169290920160200192915050565b602081526000612ac66020830184613e00565b600060208284031215613e5157600080fd5b8151612ac6816139be565b805180151581146135a357600080fd5b600060208284031215613e7e57600080fd5b612ac682613e5c565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215613ed057600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b60008060408385031215613f0357600080fd5b505080516020909101519092909150565b600080600080600060a08688031215613f2c57600080fd5b613f3586613e5c565b602087015160408801516060890151608090990151929a91995097965090945092505050565b634e487b7160e01b600052601160045260246000fd5b600082821015613f8357613f83613f5b565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff8a16815260e060208201526000613fcf60e083018a8c613f88565b67ffffffffffffffff891660408401528281036060840152613ff18189613e00565b6001600160a01b038816608085015260a0840187905283810360c0850152905061401c818587613f88565b9c9b505050505050505050505050565b6000821982111561403f5761403f613f5b565b500190565b61ffff8816815260c06020820152600061406160c0830189613e00565b67ffffffffffffffff881660408401526001600160a01b03871660608401526080830186905282810360a084015261409a818587613f88565b9a9950505050505050505050565b61ffff8716815260a0602082015260006140c660a083018789613f88565b67ffffffffffffffff861660408401526001600160a01b038516606084015282810360808401526140f78185613e00565b9998505050505050505050565b60008261412157634e487b7160e01b600052601260045260246000fd5b500490565b600081600019048311821515161561414057614140613f5b565b500290565b8881526001600160a01b0388811660208301528781166040830152861660608201526080810185905260a0810184905260e060c0820181905260009061409a9083018486613f88565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156141b757600080fd5b825160ff811681146141c857600080fd5b602084015190925067ffffffffffffffff808211156141e657600080fd5b818501915085601f8301126141fa57600080fd5b81518181111561420c5761420c61418e565b604051601f8201601f19908116603f011681019083821181831017156142345761423461418e565b8160405282815288602084870101111561424d57600080fd5b61425e836020830160208801613dd4565b80955050505050509250929050565b60008060006060848603121561428257600080fd5b835161428d816139be565b602085015190935061429e816139be565b80925050604084015190509250925092565b600080604083850312156142c357600080fd5b82516142ce816139be565b6020939093015192949293505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060001982141561438b5761438b613f5b565b5060010190565b6000806000606084860312156143a757600080fd5b83516143b281613b0a565b6020850151604086015191945092506143ca81613b1a565b809150509250925092565b600082516143e7818460208701613dd4565b919091019291505056fea2646970667358221220542011671db719c2bf3af890e7b7f90cc6b40a01b9d31e3b267472d3668c7eb764736f6c63430008090033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.