Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 14868835 | 870 days ago | IN | 0 ETH | 0.09730413 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
RebalancerModule
Compiler Version
v0.8.6+commit.11564f7e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./events.sol"; import "../../../../infiniteProxy/IProxy.sol"; contract RebalancerModule is Events { using SafeERC20 for IERC20; /** * @dev Only rebalancer gaurd. */ modifier onlyRebalancer() { require( _isRebalancer[msg.sender] || IProxy(address(this)).getAdmin() == msg.sender, "only rebalancer" ); _; } /** * @dev low gas function just to collect profit. * @notice Collected the profit & leave it in the DSA itself to optimize further on gas. */ function collectProfit( bool isWeth, // either weth or steth uint256 withdrawAmt_, uint256 amt_, uint256 unitAmt_, bytes memory oneInchData_ ) external nonReentrant onlyRebalancer { uint256 profits_ = getNewProfits(); require(amt_ <= profits_, "amount-exceeds-profit"); uint256 length_ = 1; if (withdrawAmt_ > 0) length_++; string[] memory targets_ = new string[](length_); bytes[] memory calldata_ = new bytes[](length_); address sellToken_ = isWeth ? address(wethContract) : address(stethContract); uint256 maxAmt_ = (getStethCollateralAmount() * _idealExcessAmt) / 10000; if (withdrawAmt_ > 0) { if (isWeth) { targets_[0] = "AAVE-V2-A"; calldata_[0] = abi.encodeWithSignature( "borrow(address,uint256,uint256,uint256,uint256)", address(wethContract), withdrawAmt_, 2, 0, 0 ); } else { targets_[0] = "AAVE-V2-A"; calldata_[0] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", address(stethContract), withdrawAmt_, 0, 0 ); } } targets_[length_ - 1] = "1INCH-A"; calldata_[length_ - 1] = abi.encodeWithSignature( "sell(address,address,uint256,uint256,bytes,uint256)", _token, sellToken_, amt_, unitAmt_, oneInchData_, 0 ); _vaultDsa.cast(targets_, calldata_, address(this)); if (withdrawAmt_ > 0) require( IERC20(sellToken_).balanceOf(address(_vaultDsa)) <= maxAmt_, "withdrawal-exceeds-max-limit" ); emit collectProfitLog(isWeth, withdrawAmt_, amt_, unitAmt_); } struct RebalanceOneVariables { bool isOk; uint256 i; uint256 j; uint256 length; string[] targets; bytes[] calldatas; bool criticalIsOk; bool minIsOk; } /** * @dev Rebalancer function to leverage and rebalance the position. */ function rebalanceOne( address flashTkn_, uint256 flashAmt_, uint256 route_, address[] memory vaults_, // leverage using other vaults uint256[] memory amts_, uint256 leverageAmt_, uint256 swapAmt_, // 1inch's swap amount uint256 tokenSupplyAmt_, uint256 tokenWithdrawAmt_, uint256 unitAmt_, bytes memory oneInchData_ ) external nonReentrant onlyRebalancer { if (leverageAmt_ < 1e14) leverageAmt_ = 0; if (tokenWithdrawAmt_ < _tokenMinLimit) tokenWithdrawAmt_ = 0; if (tokenSupplyAmt_ >= _tokenMinLimit) _token.safeTransfer(address(_vaultDsa), tokenSupplyAmt_); RebalanceOneVariables memory v_; v_.isOk = validateLeverageAmt(vaults_, amts_, leverageAmt_, swapAmt_); require(v_.isOk, "swap-amounts-are-not-proper"); v_.length = amts_.length; uint256 tokenDsaBal_ = _token.balanceOf(address(_vaultDsa)); if (tokenDsaBal_ >= _tokenMinLimit) v_.j += 1; if (leverageAmt_ > 0) v_.j += 1; if (flashAmt_ > 0) v_.j += 3; if (swapAmt_ > 0) v_.j += 2; // only deposit stEth in Aave if swap amt > 0. if (v_.length > 0) v_.j += v_.length; if (tokenWithdrawAmt_ > 0) v_.j += 2; v_.targets = new string[](v_.j); v_.calldatas = new bytes[](v_.j); if (tokenDsaBal_ >= _tokenMinLimit) { v_.targets[v_.i] = "AAVE-V2-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", address(_token), type(uint256).max, 0, 0 ); v_.i++; } if (leverageAmt_ > 0) { if (flashAmt_ > 0) { v_.targets[v_.i] = "AAVE-V2-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); v_.i++; } v_.targets[v_.i] = "AAVE-V2-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "borrow(address,uint256,uint256,uint256,uint256)", address(wethContract), leverageAmt_, 2, 0, 0 ); v_.i++; // Doing swaps from different vaults using deleverage to reduce other vaults riskiness if needed. // It takes WETH from vault and gives astETH at 1:1 for (uint256 k = 0; k < v_.length; k++) { v_.targets[v_.i] = "LITE-A"; // Instadapp Lite vaults connector v_.calldatas[v_.i] = abi.encodeWithSignature( "deleverage(address,uint256,uint256,uint256)", vaults_[k], amts_[k], 0, 0 ); v_.i++; } if (swapAmt_ > 0) { require(unitAmt_ > (1e18 - 10), "invalid-unit-amt"); v_.targets[v_.i] = "1INCH-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "sell(address,address,uint256,uint256,bytes,uint256)", address(stethContract), address(wethContract), swapAmt_, unitAmt_, oneInchData_, 0 ); v_.targets[v_.i + 1] = "AAVE-V2-A"; v_.calldatas[v_.i + 1] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", address(stethContract), type(uint256).max, 0, 0 ); v_.i += 2; } if (flashAmt_ > 0) { v_.targets[v_.i] = "AAVE-V2-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); v_.targets[v_.i + 1] = "INSTAPOOL-C"; v_.calldatas[v_.i + 1] = abi.encodeWithSignature( "flashPayback(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); v_.i += 2; } } if (tokenWithdrawAmt_ > 0) { v_.targets[v_.i] = "AAVE-V2-A"; v_.calldatas[v_.i] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", _token, tokenWithdrawAmt_, 0, 0 ); v_.targets[v_.i + 1] = "BASIC-A"; v_.calldatas[v_.i + 1] = abi.encodeWithSignature( "withdraw(address,uint256,address,uint256,uint256)", _token, tokenWithdrawAmt_, address(this), 0, 0 ); v_.i += 2; } if (flashAmt_ > 0) { bytes memory encodedFlashData_ = abi.encode( v_.targets, v_.calldatas ); string[] memory flashTarget_ = new string[](1); bytes[] memory flashCalldata_ = new bytes[](1); flashTarget_[0] = "INSTAPOOL-C"; flashCalldata_[0] = abi.encodeWithSignature( "flashBorrowAndCast(address,uint256,uint256,bytes,bytes)", flashTkn_, flashAmt_, route_, encodedFlashData_, "0x" ); _vaultDsa.cast(flashTarget_, flashCalldata_, address(this)); } else { if (v_.j > 0) _vaultDsa.cast(v_.targets, v_.calldatas, address(this)); } if (leverageAmt_ > 0) require( getWethBorrowRate() < _ratios.maxBorrowRate, "high-borrow-rate" ); (v_.criticalIsOk, , v_.minIsOk, , ) = validateFinalPosition(); // this will allow auth to take position to max safe limit. Only have to execute when there's a need to make other vaults safer. if (IProxy(address(this)).getAdmin() == msg.sender) { if (leverageAmt_ > 0) require(v_.criticalIsOk, "aave position risky"); } else { if (leverageAmt_ > 0) require(v_.minIsOk, "position risky after leverage"); if (tokenWithdrawAmt_ > 0) require(v_.criticalIsOk, "aave position risky"); } emit rebalanceOneLog( flashTkn_, flashAmt_, route_, vaults_, amts_, leverageAmt_, swapAmt_, tokenSupplyAmt_, tokenWithdrawAmt_, unitAmt_ ); } /** * @dev Rebalancer function for saving. To be run in times of making position less risky or to fill up the withdraw amount for users to exit */ function rebalanceTwo( address flashTkn_, uint256 flashAmt_, uint256 route_, uint256 saveAmt_, uint256 tokenSupplyAmt_, uint256 unitAmt_, bytes memory oneInchData_ ) external nonReentrant onlyRebalancer { require(unitAmt_ > (1e18 - _saveSlippage), "excess-slippage"); // TODO: set variable to update slippage? Here's it's 0.1% slippage. uint256 i; uint256 j; if (tokenSupplyAmt_ >= _tokenMinLimit) _token.safeTransfer(address(_vaultDsa), tokenSupplyAmt_); uint256 tokenDsaBal_ = _token.balanceOf(address(_vaultDsa)); if (tokenDsaBal_ >= _tokenMinLimit) j += 1; if (saveAmt_ > 0) j += 3; if (flashAmt_ > 0) j += 3; string[] memory targets_ = new string[](j); bytes[] memory calldata_ = new bytes[](j); if (tokenDsaBal_ >= _tokenMinLimit) { targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", address(_token), type(uint256).max, 0, 0 ); i++; } if (saveAmt_ > 0) { if (flashAmt_ > 0) { targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); i++; } targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", address(stethContract), saveAmt_, 0, 0 ); targets_[i + 1] = "1INCH-A"; calldata_[i + 1] = abi.encodeWithSignature( "sell(address,address,uint256,uint256,bytes,uint256)", address(wethContract), address(stethContract), saveAmt_, unitAmt_, oneInchData_, 1 // setId 1 ); targets_[i + 2] = "AAVE-V2-A"; calldata_[i + 2] = abi.encodeWithSignature( "payback(address,uint256,uint256,uint256,uint256)", address(wethContract), 0, 2, 1, // getId 1 to get the payback amount 0 ); if (flashAmt_ > 0) { targets_[i + 3] = "AAVE-V2-A"; calldata_[i + 3] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); targets_[i + 4] = "INSTAPOOL-C"; calldata_[i + 4] = abi.encodeWithSignature( "flashPayback(address,uint256,uint256,uint256)", flashTkn_, flashAmt_, 0, 0 ); } } if (flashAmt_ > 0) { bytes memory encodedFlashData_ = abi.encode(targets_, calldata_); string[] memory flashTarget_ = new string[](1); bytes[] memory flashCalldata_ = new bytes[](1); flashTarget_[0] = "INSTAPOOL-C"; flashCalldata_[0] = abi.encodeWithSignature( "flashBorrowAndCast(address,uint256,uint256,bytes,bytes)", flashTkn_, flashAmt_, route_, encodedFlashData_, "0x" ); _vaultDsa.cast(flashTarget_, flashCalldata_, address(this)); } else { if (j > 0) _vaultDsa.cast(targets_, calldata_, address(this)); } (, bool isOk_, , , ) = validateFinalPosition(); require(isOk_, "position-risky"); emit rebalanceTwoLog(flashTkn_, flashAmt_, route_, saveAmt_, unitAmt_); } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "../common/helpers.sol"; contract Events is Helpers { event collectProfitLog( bool isWeth, uint256 withdrawAmt_, uint256 amt_, uint256 unitAmt_ ); event rebalanceOneLog( address flashTkn_, uint256 flashAmt_, uint256 route_, address[] vaults_, uint256[] amts_, uint256 leverageAmt_, uint256 swapAmt_, uint256 tokenSupplyAmt_, uint256 tokenWithdrawAmt_, uint256 unitAmt_ ); event rebalanceTwoLog( address flashTkn_, uint256 flashAmt_, uint256 route_, uint256 saveAmt_, uint256 unitAmt_ ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IProxy { function getAdmin() external view returns (address); }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./variables.sol"; contract Helpers is Variables { /** * @dev reentrancy gaurd. */ modifier nonReentrant() { require(_status != 2, "ReentrancyGuard: reentrant call"); _status = 2; _; _status = 1; } /** * @dev Helper function to get current eth borrow rate on aave. */ function getWethBorrowRate() internal view returns (uint256 wethBorrowRate_) { (, , , , wethBorrowRate_, , , , , ) = aaveProtocolDataProvider .getReserveData(address(wethContract)); } /** * @dev Helper function to get current token collateral on aave. */ function getTokenCollateralAmount() internal view returns (uint256 tokenAmount_) { tokenAmount_ = _atoken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to get current steth collateral on aave. */ function getStethCollateralAmount() internal view returns (uint256 stEthAmount_) { stEthAmount_ = astethToken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to get current eth debt on aave. */ function getWethDebtAmount() internal view returns (uint256 wethDebtAmount_) { wethDebtAmount_ = awethVariableDebtToken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to token balances of everywhere. */ function getVaultBalances() public view returns ( uint256 tokenCollateralAmt_, uint256 stethCollateralAmt_, uint256 wethDebtAmt_, uint256 tokenVaultBal_, uint256 tokenDSABal_, uint256 netTokenBal_ ) { tokenCollateralAmt_ = getTokenCollateralAmount(); stethCollateralAmt_ = getStethCollateralAmount(); wethDebtAmt_ = getWethDebtAmount(); tokenVaultBal_ = _token.balanceOf(address(this)); tokenDSABal_ = _token.balanceOf(address(_vaultDsa)); netTokenBal_ = tokenCollateralAmt_ + tokenVaultBal_ + tokenDSABal_; } // returns net eth. net stETH + ETH - net ETH debt. function getNewProfits() public view returns (uint256 profits_) { uint256 stEthCol_ = getStethCollateralAmount(); uint256 stEthDsaBal_ = stethContract.balanceOf(address(_vaultDsa)); uint256 wethDsaBal_ = wethContract.balanceOf(address(_vaultDsa)); uint256 positiveEth_ = stEthCol_ + stEthDsaBal_ + wethDsaBal_; uint256 negativeEth_ = getWethDebtAmount() + _revenueEth; profits_ = negativeEth_ < positiveEth_ ? positiveEth_ - negativeEth_ : 0; } /** * @dev Helper function to get current exchange price and new revenue generated. */ function getCurrentExchangePrice() public view returns (uint256 exchangePrice_, uint256 newTokenRevenue_) { // net token balance is total balance. stETH collateral & ETH debt cancels out each other. (, , , , , uint256 netTokenBalance_) = getVaultBalances(); netTokenBalance_ -= _revenue; uint256 totalSupply_ = totalSupply(); uint256 exchangePriceWithRevenue_; if (totalSupply_ != 0) { exchangePriceWithRevenue_ = (netTokenBalance_ * 1e18) / totalSupply_; } else { exchangePriceWithRevenue_ = 1e18; } // Only calculate revenue if there's a profit if (exchangePriceWithRevenue_ > _lastRevenueExchangePrice) { uint256 newProfit_ = netTokenBalance_ - ((_lastRevenueExchangePrice * totalSupply_) / 1e18); newTokenRevenue_ = (newProfit_ * _revenueFee) / 10000; exchangePrice_ = ((netTokenBalance_ - newTokenRevenue_) * 1e18) / totalSupply_; } else { exchangePrice_ = exchangePriceWithRevenue_; } } struct ValidateFinalPosition { uint256 tokenPriceInBaseCurrency; uint256 ethPriceInBaseCurrency; uint256 excessDebtInBaseCurrency; uint256 netTokenColInBaseCurrency; uint256 netTokenSupplyInBaseCurrency; uint256 ratioMax; uint256 ratioMin; } /** * @dev Helper function to validate the safety of aave position after rebalancing. */ function validateFinalPosition() internal view returns ( bool criticalIsOk_, bool criticalGapIsOk_, bool minIsOk_, bool minGapIsOk_, bool withdrawIsOk_ ) { ( uint256 tokenColAmt_, uint256 stethColAmt_, uint256 wethDebt_, , , uint256 netTokenBal_ ) = getVaultBalances(); uint256 ethCoveringDebt_ = (stethColAmt_ * _ratios.stEthLimit) / 10000; uint256 excessDebt_ = ethCoveringDebt_ < wethDebt_ ? wethDebt_ - ethCoveringDebt_ : 0; if (excessDebt_ > 0) { IAavePriceOracle aaveOracle_ = IAavePriceOracle( aaveAddressProvider.getPriceOracle() ); ValidateFinalPosition memory validateFinalPosition_; validateFinalPosition_.tokenPriceInBaseCurrency = aaveOracle_ .getAssetPrice(address(_token)); validateFinalPosition_.ethPriceInBaseCurrency = aaveOracle_ .getAssetPrice(address(wethContract)); validateFinalPosition_.excessDebtInBaseCurrency = (excessDebt_ * validateFinalPosition_.ethPriceInBaseCurrency) / 1e18; validateFinalPosition_.netTokenColInBaseCurrency = (tokenColAmt_ * validateFinalPosition_.tokenPriceInBaseCurrency) / (10**_tokenDecimals); validateFinalPosition_.netTokenSupplyInBaseCurrency = (netTokenBal_ * validateFinalPosition_.tokenPriceInBaseCurrency) / (10**_tokenDecimals); validateFinalPosition_.ratioMax = (validateFinalPosition_.excessDebtInBaseCurrency * 10000) / validateFinalPosition_.netTokenColInBaseCurrency; validateFinalPosition_.ratioMin = (validateFinalPosition_.excessDebtInBaseCurrency * 10000) / validateFinalPosition_.netTokenSupplyInBaseCurrency; criticalIsOk_ = validateFinalPosition_.ratioMax < _ratios.maxLimit; criticalGapIsOk_ = validateFinalPosition_.ratioMax > _ratios.maxLimitGap; minIsOk_ = validateFinalPosition_.ratioMin < _ratios.minLimit; minGapIsOk_ = validateFinalPosition_.ratioMin > _ratios.minLimitGap; withdrawIsOk_ = validateFinalPosition_.ratioMax < (_ratios.maxLimit - 100); } else { criticalIsOk_ = true; minIsOk_ = true; } } /** * @dev Helper function to validate if the leverage amount is divided correctly amount other-vault-swaps and 1inch-swap . */ function validateLeverageAmt( address[] memory vaults_, uint256[] memory amts_, uint256 leverageAmt_, uint256 swapAmt_ ) internal pure returns (bool isOk_) { if (leverageAmt_ == 0 && swapAmt_ == 0) { isOk_ = true; return isOk_; } uint256 l_ = vaults_.length; isOk_ = l_ == amts_.length; if (isOk_) { uint256 totalAmt_ = swapAmt_; for (uint256 i = 0; i < l_; i++) { totalAmt_ = totalAmt_ + amts_[i]; } isOk_ = totalAmt_ <= leverageAmt_; // total amount should not be more than leverage amount isOk_ = isOk_ && ((leverageAmt_ * 9999) / 10000) < totalAmt_; // total amount should be more than (0.9999 * leverage amount). 0.01% slippage gap. } } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./interfaces.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; contract ConstantVariables is ERC20Upgradeable { IInstaIndex internal constant instaIndex = IInstaIndex(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); IERC20 internal constant wethContract = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); IERC20 internal constant stethContract = IERC20(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); IAaveProtocolDataProvider internal constant aaveProtocolDataProvider = IAaveProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); IAaveAddressProvider internal constant aaveAddressProvider = IAaveAddressProvider(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); IERC20 internal constant awethVariableDebtToken = IERC20(0xF63B34710400CAd3e044cFfDcAb00a0f32E33eCf); IERC20 internal constant astethToken = IERC20(0x1982b2F5814301d4e9a8b0201555376e62F82428); IInstaList internal constant instaList = IInstaList(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); } contract Variables is ConstantVariables { uint256 internal _status = 1; // only authorized addresses can rebalance mapping(address => bool) internal _isRebalancer; IERC20 internal _token; uint8 internal _tokenDecimals; uint256 internal _tokenMinLimit; IERC20 internal _atoken; IDSA internal _vaultDsa; struct Ratios { uint16 maxLimit; // Above this withdrawals are not allowed uint16 maxLimitGap; uint16 minLimit; // After leverage the ratio should be below minLimit & above minLimitGap uint16 minLimitGap; uint16 stEthLimit; // if 7500. Meaning stETH collateral covers 75% of the ETH debt. Excess ETH will be covered by token limit. // send borrow rate in 4 decimals from UI. In the smart contract it'll convert to 27 decimals which where is 100% uint128 maxBorrowRate; // maximum borrow rate above this leveraging should not happen } Ratios internal _ratios; // last revenue exchange price (helps in calculating revenue) // Exchange price when revenue got updated last. It'll only increase overtime. uint256 internal _lastRevenueExchangePrice; uint256 internal _revenueFee; // 1000 = 10% (10% of user's profit) uint256 internal _revenue; uint256 internal _revenueEth; uint256 internal _withdrawalFee; // 10000 = 100% uint256 internal _idealExcessAmt; // 10 means 0.1% of total stEth/Eth supply (collateral + ideal balance) uint256 internal _swapFee; // 5 means 0.05%. This is the fee on leverage function which allows swap of stETH -> ETH uint256 internal _saveSlippage; // 1e16 means 1% uint256 internal _deleverageFee; // 1 means 0.01% }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IInstaIndex { function build( address owner_, uint256 accountVersion_, address origin_ ) external returns (address account_); } interface IDSA { function cast( string[] calldata _targetNames, bytes[] calldata _datas, address _origin ) external payable returns (bytes32); } interface IAaveProtocolDataProvider { function getReserveData(address asset) external view returns ( uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp ); } interface IAaveAddressProvider { function getPriceOracle() external view returns (address); } interface IAavePriceOracle { function getAssetPrice(address _asset) external view returns (uint256); } interface TokenInterface { function approve(address, uint256) external; function transfer(address, uint256) external; function transferFrom( address, address, uint256 ) external; function deposit() external payable; function withdraw(uint256) external; function balanceOf(address) external view returns (uint256); function decimals() external view returns (uint256); function totalSupply() external view returns (uint256); } interface IInstaList { function accountID(address) external view returns (uint64); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) 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) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "./extensions/IERC20MetadataUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, _allowances[owner][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = _allowances[owner][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Spend `amount` form the allowance of `owner` toward `spender`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) 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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @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 // 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: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @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 // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; 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. * * 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 initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // 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, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// 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); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isWeth","type":"bool"},{"indexed":false,"internalType":"uint256","name":"withdrawAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unitAmt_","type":"uint256"}],"name":"collectProfitLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"flashTkn_","type":"address"},{"indexed":false,"internalType":"uint256","name":"flashAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"route_","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"vaults_","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amts_","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"leverageAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSupplyAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenWithdrawAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unitAmt_","type":"uint256"}],"name":"rebalanceOneLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"flashTkn_","type":"address"},{"indexed":false,"internalType":"uint256","name":"flashAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"route_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"saveAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unitAmt_","type":"uint256"}],"name":"rebalanceTwoLog","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isWeth","type":"bool"},{"internalType":"uint256","name":"withdrawAmt_","type":"uint256"},{"internalType":"uint256","name":"amt_","type":"uint256"},{"internalType":"uint256","name":"unitAmt_","type":"uint256"},{"internalType":"bytes","name":"oneInchData_","type":"bytes"}],"name":"collectProfit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentExchangePrice","outputs":[{"internalType":"uint256","name":"exchangePrice_","type":"uint256"},{"internalType":"uint256","name":"newTokenRevenue_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewProfits","outputs":[{"internalType":"uint256","name":"profits_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultBalances","outputs":[{"internalType":"uint256","name":"tokenCollateralAmt_","type":"uint256"},{"internalType":"uint256","name":"stethCollateralAmt_","type":"uint256"},{"internalType":"uint256","name":"wethDebtAmt_","type":"uint256"},{"internalType":"uint256","name":"tokenVaultBal_","type":"uint256"},{"internalType":"uint256","name":"tokenDSABal_","type":"uint256"},{"internalType":"uint256","name":"netTokenBal_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"flashTkn_","type":"address"},{"internalType":"uint256","name":"flashAmt_","type":"uint256"},{"internalType":"uint256","name":"route_","type":"uint256"},{"internalType":"address[]","name":"vaults_","type":"address[]"},{"internalType":"uint256[]","name":"amts_","type":"uint256[]"},{"internalType":"uint256","name":"leverageAmt_","type":"uint256"},{"internalType":"uint256","name":"swapAmt_","type":"uint256"},{"internalType":"uint256","name":"tokenSupplyAmt_","type":"uint256"},{"internalType":"uint256","name":"tokenWithdrawAmt_","type":"uint256"},{"internalType":"uint256","name":"unitAmt_","type":"uint256"},{"internalType":"bytes","name":"oneInchData_","type":"bytes"}],"name":"rebalanceOne","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"flashTkn_","type":"address"},{"internalType":"uint256","name":"flashAmt_","type":"uint256"},{"internalType":"uint256","name":"route_","type":"uint256"},{"internalType":"uint256","name":"saveAmt_","type":"uint256"},{"internalType":"uint256","name":"tokenSupplyAmt_","type":"uint256"},{"internalType":"uint256","name":"unitAmt_","type":"uint256"},{"internalType":"bytes","name":"oneInchData_","type":"bytes"}],"name":"rebalanceTwo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600160655534801561001557600080fd5b5061420f806100256000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806339509351116100a257806395d89b411161007157806395d89b4114610239578063a457c2d714610241578063a9059cbb14610254578063cc4a015814610267578063dd62ed3e1461028457600080fd5b806339509351146101e257806370a08231146101f557806372e518c21461021e578063922a167c1461023157600080fd5b80632391f3c1116100de5780632391f3c11461019857806323b872dd146101ad57806325258d0c146101c0578063313ce567146101d357600080fd5b806306fdde0314610110578063095ea7b31461012e57806318160ddd146101515780632237068514610163575b600080fd5b6101186102bd565b6040516101259190613ea6565b60405180910390f35b61014161013c366004613933565b61034f565b6040519015158152602001610125565b6035545b604051908152602001610125565b61016b610369565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610125565b6101ab6101a6366004613a44565b6104ac565b005b6101416101bb3660046138f2565b610fd1565b6101ab6101ce36600461395f565b610ff7565b60405160128152602001610125565b6101416101f0366004613933565b612155565b61015561020336600461387f565b6001600160a01b031660009081526033602052604090205490565b6101ab61022c366004613ae1565b612194565b6101556127de565b610118612969565b61014161024f366004613933565b612978565b610141610262366004613933565b612a15565b61026f612a23565b60408051928352602083019190915201610125565b6101556102923660046138b9565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102cc9061411b565b80601f01602080910402602001604051908101604052809291908181526020018280546102f89061411b565b80156103455780601f1061031a57610100808354040283529160200191610345565b820191906000526020600020905b81548152906001019060200180831161032857829003601f168201915b5050505050905090565b60003361035d818585612b1b565b60019150505b92915050565b60008060008060008061037a612c3f565b9550610384612cc9565b945061038e612d10565b6067546040516370a0823160e01b81523060048201529195506001600160a01b0316906370a082319060240160206040518083038186803b1580156103d257600080fd5b505afa1580156103e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040a9190613b4e565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015292955016906370a082319060240160206040518083038186803b15801561045357600080fd5b505afa158015610467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048b9190613b4e565b9150816104988488613f6e565b6104a29190613f6e565b9050909192939495565b606554600214156104d85760405162461bcd60e51b81526004016104cf90613ee2565b60405180910390fd5b60026065553360009081526066602052604090205460ff168061057c5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561053957600080fd5b505afa15801561054d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610571919061389c565b6001600160a01b0316145b6105985760405162461bcd60e51b81526004016104cf90613eb9565b6073546105ad90670de0b6b3a76400006140d8565b82116105ed5760405162461bcd60e51b815260206004820152600f60248201526e6578636573732d736c69707061676560881b60448201526064016104cf565b600080606854851061061657606a54606754610616916001600160a01b03918216911687612d57565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b15801561066257600080fd5b505afa158015610676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069a9190613b4e565b905060685481106106b3576106b0600183613f6e565b91505b86156106c7576106c4600383613f6e565b91505b88156106db576106d8600383613f6e565b91505b60008267ffffffffffffffff8111156106f6576106f661419d565b60405190808252806020026020018201604052801561072957816020015b60608152602001906001900390816107145790505b50905060008367ffffffffffffffff8111156107475761074761419d565b60405190808252806020026020018201604052801561077a57816020015b60608152602001906001900390816107655790505b50905060685483106108425760405180604001604052806009815260200168414156452d56322d4160b81b8152508286815181106107ba576107ba614187565b60209081029190910101526067546040516107ea916001600160a01b031690600019906000908190602401613d18565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b179052815182908790811061082857610828614187565b6020026020010181905250848061083e90614156565b9550505b8815610cd4578a156108fd5760405180604001604052806009815260200168414156452d56322d4160b81b81525082868151811061088257610882614187565b60200260200101819052508b8b6000806040516024016108a59493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b17905281518290879081106108e3576108e3614187565b602002602001018190525084806108f990614156565b9550505b60405180604001604052806009815260200168414156452d56322d4160b81b81525082868151811061093157610931614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe84896000806040516024016109689493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b17905281518290879081106109a6576109a6614187565b60200260200101819052506040518060400160405280600781526020016631494e43482d4160c81b815250828660016109df9190613f6e565b815181106109ef576109ef614187565b602002602001018190525073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ae7ab96520de3a18e5e111b5eaab095312d7fe848a89896001604051602401610a3e96959493929190613cc8565b60408051601f198184030181529190526020810180516001600160e01b031663f892b2ad60e01b17905281610a74876001613f6e565b81518110610a8457610a84614187565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b81525082866002610abf9190613f6e565b81518110610acf57610acf614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152600060448201819052600260648301526001608483015260a482015260c40160408051601f198184030181529190526020810180516001600160e01b0316634e5e60e760e01b17905281610b4c876002613f6e565b81518110610b5c57610b5c614187565b60209081029190910101528a15610cd457604080518082019091526009815268414156452d56322d4160b81b602082015282610b99876003613f6e565b81518110610ba957610ba9614187565b60200260200101819052508b8b600080604051602401610bcc9493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b17905281610c02876003613f6e565b81518110610c1257610c12614187565b60200260200101819052506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082866004610c4f9190613f6e565b81518110610c5f57610c5f614187565b60200260200101819052508b8b600080604051602401610c829493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b0316630427301d60e31b17905281610cb8876004613f6e565b81518110610cc857610cc8614187565b60200260200101819052505b8a15610e885760008282604051602001610cef929190613e3a565b60408051808303601f190181526001808452838301909252925060009190816020015b6060815260200190600190039081610d1257505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610d415790505090506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082600081518110610d8f57610d8f614187565b60200260200101819052508e8e8e85604051602401610db19493929190613de6565b60408051601f198184030181529190526020810180516001600160e01b0316634cb38df560e01b17905281518290600090610dee57610dee614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490610e2d90859085903090600401613e68565b602060405180830381600087803b158015610e4757600080fd5b505af1158015610e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7f9190613b4e565b50505050610f16565b8315610f1657606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490610ec290859085903090600401613e68565b602060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f149190613b4e565b505b6000610f20612dae565b50505091505080610f645760405162461bcd60e51b815260206004820152600e60248201526d706f736974696f6e2d7269736b7960901b60448201526064016104cf565b604080516001600160a01b038f168152602081018e90529081018c9052606081018b9052608081018990527f596a4d412b7bfc83f7fd5235652168f49285fca1b5ccd4965ebc8fde303252e29060a0015b60405180910390a1505060016065555050505050505050505050565b600033610fdf85828561319e565b610fea858585613230565b60019150505b9392505050565b6065546002141561101a5760405162461bcd60e51b81526004016104cf90613ee2565b60026065553360009081526066602052604090205460ff16806110be5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561107b57600080fd5b505afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b3919061389c565b6001600160a01b0316145b6110da5760405162461bcd60e51b81526004016104cf90613eb9565b655af3107a40008610156110ed57600095505b6068548310156110fc57600092505b606854841061112257606a54606754611122916001600160a01b03918216911686612d57565b61117060405180610100016040528060001515815260200160008152602001600081526020016000815260200160608152602001606081526020016000151581526020016000151581525090565b61117c898989896133fe565b15158082526111cd5760405162461bcd60e51b815260206004820152601b60248201527f737761702d616d6f756e74732d6172652d6e6f742d70726f706572000000000060448201526064016104cf565b87516060820152606754606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b15801561122057600080fd5b505afa158015611234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112589190613b4e565b9050606854811061127a576001826040018181516112769190613f6e565b9052505b8715611297576001826040018181516112939190613f6e565b9052505b8b156112b4576003826040018181516112b09190613f6e565b9052505b86156112d1576002826040018181516112cd9190613f6e565b9052505b6060820151156112f5578160600151826040018181516112f19190613f6e565b9052505b84156113125760028260400181815161130e9190613f6e565b9052505b816040015167ffffffffffffffff81111561132f5761132f61419d565b60405190808252806020026020018201604052801561136257816020015b606081526020019060019003908161134d5790505b506080830152604082015167ffffffffffffffff8111156113855761138561419d565b6040519080825280602002602001820160405280156113b857816020015b60608152602001906001900390816113a35790505b5060a083015260685481106114985760405180604001604052806009815260200168414156452d56322d4160b81b815250826080015183602001518151811061140357611403614187565b6020908102919091010152606754604051611433916001600160a01b031690600019906000908190602401613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a0840151908401518151811061147757611477614187565b602002602001018190525081602001805180919061149490614156565b9052505b8715611b0f578b156115685760405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106114e0576114e0614187565b60200260200101819052508c8c6000806040516024016115039493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a0840151908401518151811061154757611547614187565b602002602001018190525081602001805180919061156490614156565b9052505b60405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106115a4576115a4614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018990526002606482015260006084820181905260a482015260c40160408051601f19818403018152919052602080820180516001600160e01b031663355e69ef60e11b17905260a0840151908401518151811061162f5761162f614187565b602002602001018190525081602001805180919061164c90614156565b90525060005b826060015181101561176257604051806040016040528060068152602001654c4954452d4160d01b815250836080015184602001518151811061169757611697614187565b60200260200101819052508a81815181106116b4576116b4614187565b60200260200101518a82815181106116ce576116ce614187565b60200260200101516000806040516024016116ec9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663fad6cf0f60e01b17905260a0850151908501518151811061173057611730614187565b602002602001018190525082602001805180919061174d90614156565b9052508061175a81614156565b915050611652565b50861561197d57670de0b6b3a763fff684116117b35760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a590b5d5b9a5d0b585b5d60821b60448201526064016104cf565b6040518060400160405280600781526020016631494e43482d4160c81b81525082608001518360200151815181106117ed576117ed614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8473c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2888686600060405160240161183c96959493929190613cc8565b60408051601f19818403018152919052602080820180516001600160e01b031663f892b2ad60e01b17905260a0840151908401518151811061188057611880614187565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b8152508260800151836020015160016118c39190613f6e565b815181106118d3576118d3614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8460001960008060405160240161190c9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a08401519084015161194b906001613f6e565b8151811061195b5761195b614187565b60200260200101819052506002826020018181516119799190613f6e565b9052505b8b15611b0f5760405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106119bf576119bf614187565b60200260200101819052508c8c6000806040516024016119e29493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b03166322996bbb60e11b17905260a08401519084015181518110611a2657611a26614187565b60200260200101819052506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b815250826080015183602001516001611a6b9190613f6e565b81518110611a7b57611a7b614187565b60200260200101819052508c8c600080604051602401611a9e9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b0316630427301d60e31b17905260a084015190840151611add906001613f6e565b81518110611aed57611aed614187565b6020026020010181905250600282602001818151611b0b9190613f6e565b9052505b8415611cc45760405180604001604052806009815260200168414156452d56322d4160b81b8152508260800151836020015181518110611b5157611b51614187565b6020908102919091010152606754604051611b7f916001600160a01b03169087906000908190602401613d18565b60408051601f19818403018152919052602080820180516001600160e01b03166322996bbb60e11b17905260a08401519084015181518110611bc357611bc3614187565b60200260200101819052506040518060400160405280600781526020016642415349432d4160c81b815250826080015183602001516001611c049190613f6e565b81518110611c1457611c14614187565b60209081029190910101526067546040516001600160a01b0390911660248201526044810186905230606482015260006084820181905260a482015260c40160408051601f19818403018152919052602080820180516001600160e01b03166325e9d5c160e11b17905260a084015190840151611c92906001613f6e565b81518110611ca257611ca2614187565b6020026020010181905250600282602001818151611cc09190613f6e565b9052505b8b15611e8057600082608001518360a00151604051602001611ce7929190613e3a565b60408051808303601f190181526001808452838301909252925060009190816020015b6060815260200190600190039081611d0a57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081611d395790505090506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082600081518110611d8757611d87614187565b60200260200101819052508f8f8f85604051602401611da99493929190613de6565b60408051601f198184030181529190526020810180516001600160e01b0316634cb38df560e01b17905281518290600090611de657611de6614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490611e2590859085903090600401613e68565b602060405180830381600087803b158015611e3f57600080fd5b505af1158015611e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e779190613b4e565b50505050611f1a565b604082015115611f1a57606a54608083015160a08401516040516324c1324d60e21b81526001600160a01b0390931692639304c93492611ec69290913090600401613e68565b602060405180830381600087803b158015611ee057600080fd5b505af1158015611ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f189190613b4e565b505b8715611f8457606b54600160501b90046fffffffffffffffffffffffffffffffff16611f446134a5565b10611f845760405162461bcd60e51b815260206004820152601060248201526f686967682d626f72726f772d7261746560801b60448201526064016104cf565b611f8c612dae565b5050151560e085015250151560c083015260408051636e9960c360e01b8152905133913091636e9960c391600480820192602092909190829003018186803b158015611fd757600080fd5b505afa158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f919061389c565b6001600160a01b0316141561207057871561206b578160c0015161206b5760405162461bcd60e51b81526020600482015260136024820152726161766520706f736974696f6e207269736b7960681b60448201526064016104cf565b612114565b87156120c7578160e001516120c75760405162461bcd60e51b815260206004820152601d60248201527f706f736974696f6e207269736b79206166746572206c6576657261676500000060448201526064016104cf565b8415612114578160c001516121145760405162461bcd60e51b81526020600482015260136024820152726161766520706f736974696f6e207269736b7960681b60448201526064016104cf565b7f851fb501d96f6e1b2d13400466666b7b0180eb3ec3010b5cb3b238106efe73d58d8d8d8d8d8d8d8d8d8d604051610fb59a99989796959493929190613d44565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061035d908290869061218f908790613f6e565b612b1b565b606554600214156121b75760405162461bcd60e51b81526004016104cf90613ee2565b60026065553360009081526066602052604090205460ff168061225b5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561221857600080fd5b505afa15801561222c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612250919061389c565b6001600160a01b0316145b6122775760405162461bcd60e51b81526004016104cf90613eb9565b60006122816127de565b9050808411156122cb5760405162461bcd60e51b8152602060048201526015602482015274185b5bdd5b9d0b595e18d959591ccb5c1c9bd99a5d605a1b60448201526064016104cf565b600185156122e157806122dd81614156565b9150505b60008167ffffffffffffffff8111156122fc576122fc61419d565b60405190808252806020026020018201604052801561232f57816020015b606081526020019060019003908161231a5790505b50905060008267ffffffffffffffff81111561234d5761234d61419d565b60405190808252806020026020018201604052801561238057816020015b606081526020019060019003908161236b5790505b5090506000896123a45773ae7ab96520de3a18e5e111b5eaab095312d7fe846123ba565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b905060006127106071546123cc612cc9565b6123d69190614096565b6123e09190613f86565b9050891561256c578a156124b75760405180604001604052806009815260200168414156452d56322d4160b81b8152508460008151811061242357612423614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018b90526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b031663355e69ef60e11b179052835184906000906124a7576124a7614187565b602002602001018190525061256c565b60405180604001604052806009815260200168414156452d56322d4160b81b815250846000815181106124ec576124ec614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe848a6000806040516024016125239493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b1790528351849060009061256057612560614187565b60200260200101819052505b60408051808201909152600781526631494e43482d4160c81b6020820152846125966001886140d8565b815181106125a6576125a6614187565b60209081029190910101526067546040516125d8916001600160a01b03169084908c908c908c90600090602401613cc8565b60408051601f198184030181529190526020810180516001600160e01b031663f892b2ad60e01b1790528361260e6001886140d8565b8151811061261e5761261e614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c9349061265d90879087903090600401613e68565b602060405180830381600087803b15801561267757600080fd5b505af115801561268b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126af9190613b4e565b50891561278257606a546040516370a0823160e01b81526001600160a01b03918216600482015282918416906370a082319060240160206040518083038186803b1580156126fc57600080fd5b505afa158015612710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127349190613b4e565b11156127825760405162461bcd60e51b815260206004820152601c60248201527f7769746864726177616c2d657863656564732d6d61782d6c696d69740000000060448201526064016104cf565b604080518c15158152602081018c90529081018a9052606081018990527f1b6bca1d8067a19fcca43daf98ef27e5e1efcdb599eb8939519a1b9dc6604ec19060800160405180910390a150506001606555505050505050505050565b6000806127e9612cc9565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319060240160206040518083038186803b15801561284657600080fd5b505afa15801561285a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287e9190613b4e565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a082319060240160206040518083038186803b1580156128db57600080fd5b505afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613b4e565b90506000816129228486613f6e565b61292c9190613f6e565b90506000606f5461293b612d10565b6129459190613f6e565b905081811061295557600061295f565b61295f81836140d8565b9550505050505090565b6060603780546102cc9061411b565b3360008181526034602090815260408083206001600160a01b0387168452909152812054909190838110156129fd5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104cf565b612a0a8286868403612b1b565b506001949350505050565b60003361035d818585613230565b6000806000612a30610369565b95505050505050606e5481612a4591906140d8565b90506000612a5260355490565b905060008115612a805781612a6f84670de0b6b3a7640000614096565b612a799190613f86565b9050612a8b565b50670de0b6b3a76400005b606c54811115612b10576000670de0b6b3a764000083606c54612aae9190614096565b612ab89190613f86565b612ac290856140d8565b9050612710606d5482612ad59190614096565b612adf9190613f86565b945082612aec86866140d8565b612afe90670de0b6b3a7640000614096565b612b089190613f86565b955050612b14565b8094505b5050509091565b6001600160a01b038316612b7d5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104cf565b6001600160a01b038216612bde5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104cf565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b606954606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a08231906024015b60206040518083038186803b158015612c8c57600080fd5b505afa158015612ca0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc49190613b4e565b905090565b606a546040516370a0823160e01b81526001600160a01b039091166004820152600090731982b2f5814301d4e9a8b0201555376e62f82428906370a0823190602401612c74565b606a546040516370a0823160e01b81526001600160a01b03909116600482015260009073f63b34710400cad3e044cffdcab00a0f32e33ecf906370a0823190602401612c74565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612da990849061354e565b505050565b6000806000806000806000806000612dc4610369565b606b549599509397509195509193506000926127109250612df6915068010000000000000000900461ffff1686614096565b612e009190613f86565b90506000838210612e12576000612e1c565b612e1c82856140d8565b9050801561318857600073b53c1a33016b2dc2ff3653530bff1848a515c8c56001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015612e7357600080fd5b505afa158015612e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eab919061389c565b9050612eed6040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60675460405163b3596f0760e01b81526001600160a01b0391821660048201529083169063b3596f079060240160206040518083038186803b158015612f3257600080fd5b505afa158015612f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6a9190613b4e565b815260405163b3596f0760e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b0383169063b3596f079060240160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff79190613b4e565b60208201819052670de0b6b3a7640000906130129085614096565b61301c9190613f86565b604082015260675461303990600160a01b900460ff16600a613feb565b8151613045908a614096565b61304f9190613f86565b606082015260675461306c90600160a01b900460ff16600a613feb565b81516130789087614096565b6130829190613f86565b60808201526060810151604082015161309d90612710614096565b6130a79190613f86565b60a0820152608081015160408201516130c290612710614096565b6130cc9190613f86565b8160c0018181525050606b60000160009054906101000a900461ffff1661ffff168160a00151109c50606b60000160029054906101000a900461ffff1661ffff168160a00151119b50606b60000160049054906101000a900461ffff1661ffff168160c00151109a50606b60000160069054906101000a900461ffff1661ffff168160c001511199506064606b60000160009054906101000a900461ffff1661317591906140b5565b61ffff168160a001511098505050613191565b60019a50600198505b5050505050509091929394565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461322a578181101561321d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016104cf565b61322a8484848403612b1b565b50505050565b6001600160a01b0383166132945760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104cf565b6001600160a01b0382166132f65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104cf565b6001600160a01b0383166000908152603360205260409020548181101561336e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016104cf565b6001600160a01b038085166000908152603360205260408082208585039055918516815290812080548492906133a5908490613f6e565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133f191815260200190565b60405180910390a361322a565b60008215801561340c575081155b156134195750600161349d565b5083518351811490811561349b578260005b8281101561346c5786818151811061344557613445614187565b6020026020010151826134589190613f6e565b91508061346481614156565b91505061342b565b5084811115925082801561349757508061271061348b8761270f614096565b6134959190613f86565b105b9250505b505b949350505050565b6040516335ea6a7560e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600482015260009073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b15801561350757600080fd5b505afa15801561351b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353f9190613b67565b50939998505050505050505050565b60006135a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136209092919063ffffffff16565b805190915015612da957808060200190518101906135c19190613ac4565b612da95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104cf565b606061349d8484600085856001600160a01b0385163b6136825760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104cf565b600080866001600160a01b0316858760405161369e9190613cac565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b5091509150613497828286606083156136fa575081610ff0565b82511561370a5782518084602001fd5b8160405162461bcd60e51b81526004016104cf9190613ea6565b803561372f816141b3565b919050565b600082601f83011261374557600080fd5b8135602061375a61375583613f4a565b613f19565b80838252828201915082860187848660051b890101111561377a57600080fd5b60005b858110156137a2578135613790816141b3565b8452928401929084019060010161377d565b5090979650505050505050565b600082601f8301126137c057600080fd5b813560206137d061375583613f4a565b80838252828201915082860187848660051b89010111156137f057600080fd5b60005b858110156137a2578135845292840192908401906001016137f3565b600082601f83011261382057600080fd5b813567ffffffffffffffff81111561383a5761383a61419d565b61384d601f8201601f1916602001613f19565b81815284602083860101111561386257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561389157600080fd5b8135610ff0816141b3565b6000602082840312156138ae57600080fd5b8151610ff0816141b3565b600080604083850312156138cc57600080fd5b82356138d7816141b3565b915060208301356138e7816141b3565b809150509250929050565b60008060006060848603121561390757600080fd5b8335613912816141b3565b92506020840135613922816141b3565b929592945050506040919091013590565b6000806040838503121561394657600080fd5b8235613951816141b3565b946020939093013593505050565b60008060008060008060008060008060006101608c8e03121561398157600080fd5b61398a8c613724565b9a5060208c0135995060408c0135985067ffffffffffffffff8060608e013511156139b457600080fd5b6139c48e60608f01358f01613734565b98508060808e013511156139d757600080fd5b6139e78e60808f01358f016137af565b975060a08d0135965060c08d0135955060e08d013594506101008d013593506101208d01359250806101408e01351115613a2057600080fd5b50613a328d6101408e01358e0161380f565b90509295989b509295989b9093969950565b600080600080600080600060e0888a031215613a5f57600080fd5b8735613a6a816141b3565b96506020880135955060408801359450606088013593506080880135925060a0880135915060c088013567ffffffffffffffff811115613aa957600080fd5b613ab58a828b0161380f565b91505092959891949750929550565b600060208284031215613ad657600080fd5b8151610ff0816141cb565b600080600080600060a08688031215613af957600080fd5b8535613b04816141cb565b9450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115613b3557600080fd5b613b418882890161380f565b9150509295509295909350565b600060208284031215613b6057600080fd5b5051919050565b6000806000806000806000806000806101408b8d031215613b8757600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015164ffffffffff81168114613bdd57600080fd5b809150509295989b9194979a5092959850565b600081518084526020808501808196508360051b8101915082860160005b85811015613c38578284038952613c26848351613c80565b98850198935090840190600101613c0e565b5091979650505050505050565b600081518084526020808501945080840160005b83811015613c7557815187529582019590820190600101613c59565b509495945050505050565b60008151808452613c988160208601602086016140ef565b601f01601f19169290920160200192915050565b60008251613cbe8184602087016140ef565b9190910192915050565b6001600160a01b03878116825286166020820152604081018590526060810184905260c060808201819052600090613d0290830185613c80565b905060ff831660a0830152979650505050505050565b6001600160a01b03949094168452602084019290925260ff908116604084015216606082015260800190565b6001600160a01b038b8116825260208083018c9052604083018b9052610140606084018190528a519084018190526000926101608501928c810192855b81811015613d9f578451841686529482019493820193600101613d81565b50505050508281036080840152613db6818a613c45565b60a0840198909852505060c081019490945260e08401929092526101008301526101209091015295945050505050565b60018060a01b038516815283602082015282604082015260a060608201526000613e1360a0830184613c80565b82810360808401526002815261060f60f31b60208201526040810191505095945050505050565b604081526000613e4d6040830185613bf0565b8281036020840152613e5f8185613bf0565b95945050505050565b606081526000613e7b6060830186613bf0565b8281036020840152613e8d8186613bf0565b91505060018060a01b0383166040830152949350505050565b602081526000610ff06020830184613c80565b6020808252600f908201526e37b7363c903932b130b630b731b2b960891b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f4257613f4261419d565b604052919050565b600067ffffffffffffffff821115613f6457613f6461419d565b5060051b60200190565b60008219821115613f8157613f81614171565b500190565b600082613fa357634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115613fe3578160001904821115613fc957613fc9614171565b80851615613fd657918102915b93841c9390800290613fad565b509250929050565b6000610ff060ff84168360008261400457506001610363565b8161401157506000610363565b816001811461402757600281146140315761404d565b6001915050610363565b60ff84111561404257614042614171565b50506001821b610363565b5060208310610133831016604e8410600b8410161715614070575081810a610363565b61407a8383613fa8565b806000190482111561408e5761408e614171565b029392505050565b60008160001904831182151516156140b0576140b0614171565b500290565b600061ffff838116908316818110156140d0576140d0614171565b039392505050565b6000828210156140ea576140ea614171565b500390565b60005b8381101561410a5781810151838201526020016140f2565b8381111561322a5750506000910152565b600181811c9082168061412f57607f821691505b6020821081141561415057634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561416a5761416a614171565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146141c857600080fd5b50565b80151581146141c857600080fdfea264697066735822122060404c8715140903c5622b9b1357c3c9d3ebf9957808a5544217ae458286ac1664736f6c63430008060033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061010b5760003560e01c806339509351116100a257806395d89b411161007157806395d89b4114610239578063a457c2d714610241578063a9059cbb14610254578063cc4a015814610267578063dd62ed3e1461028457600080fd5b806339509351146101e257806370a08231146101f557806372e518c21461021e578063922a167c1461023157600080fd5b80632391f3c1116100de5780632391f3c11461019857806323b872dd146101ad57806325258d0c146101c0578063313ce567146101d357600080fd5b806306fdde0314610110578063095ea7b31461012e57806318160ddd146101515780632237068514610163575b600080fd5b6101186102bd565b6040516101259190613ea6565b60405180910390f35b61014161013c366004613933565b61034f565b6040519015158152602001610125565b6035545b604051908152602001610125565b61016b610369565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610125565b6101ab6101a6366004613a44565b6104ac565b005b6101416101bb3660046138f2565b610fd1565b6101ab6101ce36600461395f565b610ff7565b60405160128152602001610125565b6101416101f0366004613933565b612155565b61015561020336600461387f565b6001600160a01b031660009081526033602052604090205490565b6101ab61022c366004613ae1565b612194565b6101556127de565b610118612969565b61014161024f366004613933565b612978565b610141610262366004613933565b612a15565b61026f612a23565b60408051928352602083019190915201610125565b6101556102923660046138b9565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102cc9061411b565b80601f01602080910402602001604051908101604052809291908181526020018280546102f89061411b565b80156103455780601f1061031a57610100808354040283529160200191610345565b820191906000526020600020905b81548152906001019060200180831161032857829003601f168201915b5050505050905090565b60003361035d818585612b1b565b60019150505b92915050565b60008060008060008061037a612c3f565b9550610384612cc9565b945061038e612d10565b6067546040516370a0823160e01b81523060048201529195506001600160a01b0316906370a082319060240160206040518083038186803b1580156103d257600080fd5b505afa1580156103e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040a9190613b4e565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015292955016906370a082319060240160206040518083038186803b15801561045357600080fd5b505afa158015610467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048b9190613b4e565b9150816104988488613f6e565b6104a29190613f6e565b9050909192939495565b606554600214156104d85760405162461bcd60e51b81526004016104cf90613ee2565b60405180910390fd5b60026065553360009081526066602052604090205460ff168061057c5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561053957600080fd5b505afa15801561054d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610571919061389c565b6001600160a01b0316145b6105985760405162461bcd60e51b81526004016104cf90613eb9565b6073546105ad90670de0b6b3a76400006140d8565b82116105ed5760405162461bcd60e51b815260206004820152600f60248201526e6578636573732d736c69707061676560881b60448201526064016104cf565b600080606854851061061657606a54606754610616916001600160a01b03918216911687612d57565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b15801561066257600080fd5b505afa158015610676573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061069a9190613b4e565b905060685481106106b3576106b0600183613f6e565b91505b86156106c7576106c4600383613f6e565b91505b88156106db576106d8600383613f6e565b91505b60008267ffffffffffffffff8111156106f6576106f661419d565b60405190808252806020026020018201604052801561072957816020015b60608152602001906001900390816107145790505b50905060008367ffffffffffffffff8111156107475761074761419d565b60405190808252806020026020018201604052801561077a57816020015b60608152602001906001900390816107655790505b50905060685483106108425760405180604001604052806009815260200168414156452d56322d4160b81b8152508286815181106107ba576107ba614187565b60209081029190910101526067546040516107ea916001600160a01b031690600019906000908190602401613d18565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b179052815182908790811061082857610828614187565b6020026020010181905250848061083e90614156565b9550505b8815610cd4578a156108fd5760405180604001604052806009815260200168414156452d56322d4160b81b81525082868151811061088257610882614187565b60200260200101819052508b8b6000806040516024016108a59493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b17905281518290879081106108e3576108e3614187565b602002602001018190525084806108f990614156565b9550505b60405180604001604052806009815260200168414156452d56322d4160b81b81525082868151811061093157610931614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe84896000806040516024016109689493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b17905281518290879081106109a6576109a6614187565b60200260200101819052506040518060400160405280600781526020016631494e43482d4160c81b815250828660016109df9190613f6e565b815181106109ef576109ef614187565b602002602001018190525073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ae7ab96520de3a18e5e111b5eaab095312d7fe848a89896001604051602401610a3e96959493929190613cc8565b60408051601f198184030181529190526020810180516001600160e01b031663f892b2ad60e01b17905281610a74876001613f6e565b81518110610a8457610a84614187565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b81525082866002610abf9190613f6e565b81518110610acf57610acf614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152600060448201819052600260648301526001608483015260a482015260c40160408051601f198184030181529190526020810180516001600160e01b0316634e5e60e760e01b17905281610b4c876002613f6e565b81518110610b5c57610b5c614187565b60209081029190910101528a15610cd457604080518082019091526009815268414156452d56322d4160b81b602082015282610b99876003613f6e565b81518110610ba957610ba9614187565b60200260200101819052508b8b600080604051602401610bcc9493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b17905281610c02876003613f6e565b81518110610c1257610c12614187565b60200260200101819052506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082866004610c4f9190613f6e565b81518110610c5f57610c5f614187565b60200260200101819052508b8b600080604051602401610c829493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b0316630427301d60e31b17905281610cb8876004613f6e565b81518110610cc857610cc8614187565b60200260200101819052505b8a15610e885760008282604051602001610cef929190613e3a565b60408051808303601f190181526001808452838301909252925060009190816020015b6060815260200190600190039081610d1257505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610d415790505090506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082600081518110610d8f57610d8f614187565b60200260200101819052508e8e8e85604051602401610db19493929190613de6565b60408051601f198184030181529190526020810180516001600160e01b0316634cb38df560e01b17905281518290600090610dee57610dee614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490610e2d90859085903090600401613e68565b602060405180830381600087803b158015610e4757600080fd5b505af1158015610e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7f9190613b4e565b50505050610f16565b8315610f1657606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490610ec290859085903090600401613e68565b602060405180830381600087803b158015610edc57600080fd5b505af1158015610ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f149190613b4e565b505b6000610f20612dae565b50505091505080610f645760405162461bcd60e51b815260206004820152600e60248201526d706f736974696f6e2d7269736b7960901b60448201526064016104cf565b604080516001600160a01b038f168152602081018e90529081018c9052606081018b9052608081018990527f596a4d412b7bfc83f7fd5235652168f49285fca1b5ccd4965ebc8fde303252e29060a0015b60405180910390a1505060016065555050505050505050505050565b600033610fdf85828561319e565b610fea858585613230565b60019150505b9392505050565b6065546002141561101a5760405162461bcd60e51b81526004016104cf90613ee2565b60026065553360009081526066602052604090205460ff16806110be5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561107b57600080fd5b505afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b3919061389c565b6001600160a01b0316145b6110da5760405162461bcd60e51b81526004016104cf90613eb9565b655af3107a40008610156110ed57600095505b6068548310156110fc57600092505b606854841061112257606a54606754611122916001600160a01b03918216911686612d57565b61117060405180610100016040528060001515815260200160008152602001600081526020016000815260200160608152602001606081526020016000151581526020016000151581525090565b61117c898989896133fe565b15158082526111cd5760405162461bcd60e51b815260206004820152601b60248201527f737761702d616d6f756e74732d6172652d6e6f742d70726f706572000000000060448201526064016104cf565b87516060820152606754606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b15801561122057600080fd5b505afa158015611234573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112589190613b4e565b9050606854811061127a576001826040018181516112769190613f6e565b9052505b8715611297576001826040018181516112939190613f6e565b9052505b8b156112b4576003826040018181516112b09190613f6e565b9052505b86156112d1576002826040018181516112cd9190613f6e565b9052505b6060820151156112f5578160600151826040018181516112f19190613f6e565b9052505b84156113125760028260400181815161130e9190613f6e565b9052505b816040015167ffffffffffffffff81111561132f5761132f61419d565b60405190808252806020026020018201604052801561136257816020015b606081526020019060019003908161134d5790505b506080830152604082015167ffffffffffffffff8111156113855761138561419d565b6040519080825280602002602001820160405280156113b857816020015b60608152602001906001900390816113a35790505b5060a083015260685481106114985760405180604001604052806009815260200168414156452d56322d4160b81b815250826080015183602001518151811061140357611403614187565b6020908102919091010152606754604051611433916001600160a01b031690600019906000908190602401613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a0840151908401518151811061147757611477614187565b602002602001018190525081602001805180919061149490614156565b9052505b8715611b0f578b156115685760405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106114e0576114e0614187565b60200260200101819052508c8c6000806040516024016115039493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a0840151908401518151811061154757611547614187565b602002602001018190525081602001805180919061156490614156565b9052505b60405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106115a4576115a4614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018990526002606482015260006084820181905260a482015260c40160408051601f19818403018152919052602080820180516001600160e01b031663355e69ef60e11b17905260a0840151908401518151811061162f5761162f614187565b602002602001018190525081602001805180919061164c90614156565b90525060005b826060015181101561176257604051806040016040528060068152602001654c4954452d4160d01b815250836080015184602001518151811061169757611697614187565b60200260200101819052508a81815181106116b4576116b4614187565b60200260200101518a82815181106116ce576116ce614187565b60200260200101516000806040516024016116ec9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663fad6cf0f60e01b17905260a0850151908501518151811061173057611730614187565b602002602001018190525082602001805180919061174d90614156565b9052508061175a81614156565b915050611652565b50861561197d57670de0b6b3a763fff684116117b35760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a590b5d5b9a5d0b585b5d60821b60448201526064016104cf565b6040518060400160405280600781526020016631494e43482d4160c81b81525082608001518360200151815181106117ed576117ed614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8473c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2888686600060405160240161183c96959493929190613cc8565b60408051601f19818403018152919052602080820180516001600160e01b031663f892b2ad60e01b17905260a0840151908401518151811061188057611880614187565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b8152508260800151836020015160016118c39190613f6e565b815181106118d3576118d3614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8460001960008060405160240161190c9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b031663ce88b43960e01b17905260a08401519084015161194b906001613f6e565b8151811061195b5761195b614187565b60200260200101819052506002826020018181516119799190613f6e565b9052505b8b15611b0f5760405180604001604052806009815260200168414156452d56322d4160b81b81525082608001518360200151815181106119bf576119bf614187565b60200260200101819052508c8c6000806040516024016119e29493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b03166322996bbb60e11b17905260a08401519084015181518110611a2657611a26614187565b60200260200101819052506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b815250826080015183602001516001611a6b9190613f6e565b81518110611a7b57611a7b614187565b60200260200101819052508c8c600080604051602401611a9e9493929190613d18565b60408051601f19818403018152919052602080820180516001600160e01b0316630427301d60e31b17905260a084015190840151611add906001613f6e565b81518110611aed57611aed614187565b6020026020010181905250600282602001818151611b0b9190613f6e565b9052505b8415611cc45760405180604001604052806009815260200168414156452d56322d4160b81b8152508260800151836020015181518110611b5157611b51614187565b6020908102919091010152606754604051611b7f916001600160a01b03169087906000908190602401613d18565b60408051601f19818403018152919052602080820180516001600160e01b03166322996bbb60e11b17905260a08401519084015181518110611bc357611bc3614187565b60200260200101819052506040518060400160405280600781526020016642415349432d4160c81b815250826080015183602001516001611c049190613f6e565b81518110611c1457611c14614187565b60209081029190910101526067546040516001600160a01b0390911660248201526044810186905230606482015260006084820181905260a482015260c40160408051601f19818403018152919052602080820180516001600160e01b03166325e9d5c160e11b17905260a084015190840151611c92906001613f6e565b81518110611ca257611ca2614187565b6020026020010181905250600282602001818151611cc09190613f6e565b9052505b8b15611e8057600082608001518360a00151604051602001611ce7929190613e3a565b60408051808303601f190181526001808452838301909252925060009190816020015b6060815260200190600190039081611d0a57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081611d395790505090506040518060400160405280600b81526020016a494e535441504f4f4c2d4360a81b81525082600081518110611d8757611d87614187565b60200260200101819052508f8f8f85604051602401611da99493929190613de6565b60408051601f198184030181529190526020810180516001600160e01b0316634cb38df560e01b17905281518290600090611de657611de6614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490611e2590859085903090600401613e68565b602060405180830381600087803b158015611e3f57600080fd5b505af1158015611e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e779190613b4e565b50505050611f1a565b604082015115611f1a57606a54608083015160a08401516040516324c1324d60e21b81526001600160a01b0390931692639304c93492611ec69290913090600401613e68565b602060405180830381600087803b158015611ee057600080fd5b505af1158015611ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f189190613b4e565b505b8715611f8457606b54600160501b90046fffffffffffffffffffffffffffffffff16611f446134a5565b10611f845760405162461bcd60e51b815260206004820152601060248201526f686967682d626f72726f772d7261746560801b60448201526064016104cf565b611f8c612dae565b5050151560e085015250151560c083015260408051636e9960c360e01b8152905133913091636e9960c391600480820192602092909190829003018186803b158015611fd757600080fd5b505afa158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f919061389c565b6001600160a01b0316141561207057871561206b578160c0015161206b5760405162461bcd60e51b81526020600482015260136024820152726161766520706f736974696f6e207269736b7960681b60448201526064016104cf565b612114565b87156120c7578160e001516120c75760405162461bcd60e51b815260206004820152601d60248201527f706f736974696f6e207269736b79206166746572206c6576657261676500000060448201526064016104cf565b8415612114578160c001516121145760405162461bcd60e51b81526020600482015260136024820152726161766520706f736974696f6e207269736b7960681b60448201526064016104cf565b7f851fb501d96f6e1b2d13400466666b7b0180eb3ec3010b5cb3b238106efe73d58d8d8d8d8d8d8d8d8d8d604051610fb59a99989796959493929190613d44565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061035d908290869061218f908790613f6e565b612b1b565b606554600214156121b75760405162461bcd60e51b81526004016104cf90613ee2565b60026065553360009081526066602052604090205460ff168061225b5750336001600160a01b0316306001600160a01b0316636e9960c36040518163ffffffff1660e01b815260040160206040518083038186803b15801561221857600080fd5b505afa15801561222c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612250919061389c565b6001600160a01b0316145b6122775760405162461bcd60e51b81526004016104cf90613eb9565b60006122816127de565b9050808411156122cb5760405162461bcd60e51b8152602060048201526015602482015274185b5bdd5b9d0b595e18d959591ccb5c1c9bd99a5d605a1b60448201526064016104cf565b600185156122e157806122dd81614156565b9150505b60008167ffffffffffffffff8111156122fc576122fc61419d565b60405190808252806020026020018201604052801561232f57816020015b606081526020019060019003908161231a5790505b50905060008267ffffffffffffffff81111561234d5761234d61419d565b60405190808252806020026020018201604052801561238057816020015b606081526020019060019003908161236b5790505b5090506000896123a45773ae7ab96520de3a18e5e111b5eaab095312d7fe846123ba565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b905060006127106071546123cc612cc9565b6123d69190614096565b6123e09190613f86565b9050891561256c578a156124b75760405180604001604052806009815260200168414156452d56322d4160b81b8152508460008151811061242357612423614187565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018b90526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b031663355e69ef60e11b179052835184906000906124a7576124a7614187565b602002602001018190525061256c565b60405180604001604052806009815260200168414156452d56322d4160b81b815250846000815181106124ec576124ec614187565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe848a6000806040516024016125239493929190613d18565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b1790528351849060009061256057612560614187565b60200260200101819052505b60408051808201909152600781526631494e43482d4160c81b6020820152846125966001886140d8565b815181106125a6576125a6614187565b60209081029190910101526067546040516125d8916001600160a01b03169084908c908c908c90600090602401613cc8565b60408051601f198184030181529190526020810180516001600160e01b031663f892b2ad60e01b1790528361260e6001886140d8565b8151811061261e5761261e614187565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c9349061265d90879087903090600401613e68565b602060405180830381600087803b15801561267757600080fd5b505af115801561268b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126af9190613b4e565b50891561278257606a546040516370a0823160e01b81526001600160a01b03918216600482015282918416906370a082319060240160206040518083038186803b1580156126fc57600080fd5b505afa158015612710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127349190613b4e565b11156127825760405162461bcd60e51b815260206004820152601c60248201527f7769746864726177616c2d657863656564732d6d61782d6c696d69740000000060448201526064016104cf565b604080518c15158152602081018c90529081018a9052606081018990527f1b6bca1d8067a19fcca43daf98ef27e5e1efcdb599eb8939519a1b9dc6604ec19060800160405180910390a150506001606555505050505050505050565b6000806127e9612cc9565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319060240160206040518083038186803b15801561284657600080fd5b505afa15801561285a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061287e9190613b4e565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a082319060240160206040518083038186803b1580156128db57600080fd5b505afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613b4e565b90506000816129228486613f6e565b61292c9190613f6e565b90506000606f5461293b612d10565b6129459190613f6e565b905081811061295557600061295f565b61295f81836140d8565b9550505050505090565b6060603780546102cc9061411b565b3360008181526034602090815260408083206001600160a01b0387168452909152812054909190838110156129fd5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104cf565b612a0a8286868403612b1b565b506001949350505050565b60003361035d818585613230565b6000806000612a30610369565b95505050505050606e5481612a4591906140d8565b90506000612a5260355490565b905060008115612a805781612a6f84670de0b6b3a7640000614096565b612a799190613f86565b9050612a8b565b50670de0b6b3a76400005b606c54811115612b10576000670de0b6b3a764000083606c54612aae9190614096565b612ab89190613f86565b612ac290856140d8565b9050612710606d5482612ad59190614096565b612adf9190613f86565b945082612aec86866140d8565b612afe90670de0b6b3a7640000614096565b612b089190613f86565b955050612b14565b8094505b5050509091565b6001600160a01b038316612b7d5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104cf565b6001600160a01b038216612bde5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104cf565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b606954606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a08231906024015b60206040518083038186803b158015612c8c57600080fd5b505afa158015612ca0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc49190613b4e565b905090565b606a546040516370a0823160e01b81526001600160a01b039091166004820152600090731982b2f5814301d4e9a8b0201555376e62f82428906370a0823190602401612c74565b606a546040516370a0823160e01b81526001600160a01b03909116600482015260009073f63b34710400cad3e044cffdcab00a0f32e33ecf906370a0823190602401612c74565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612da990849061354e565b505050565b6000806000806000806000806000612dc4610369565b606b549599509397509195509193506000926127109250612df6915068010000000000000000900461ffff1686614096565b612e009190613f86565b90506000838210612e12576000612e1c565b612e1c82856140d8565b9050801561318857600073b53c1a33016b2dc2ff3653530bff1848a515c8c56001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b158015612e7357600080fd5b505afa158015612e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eab919061389c565b9050612eed6040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60675460405163b3596f0760e01b81526001600160a01b0391821660048201529083169063b3596f079060240160206040518083038186803b158015612f3257600080fd5b505afa158015612f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6a9190613b4e565b815260405163b3596f0760e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b0383169063b3596f079060240160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff79190613b4e565b60208201819052670de0b6b3a7640000906130129085614096565b61301c9190613f86565b604082015260675461303990600160a01b900460ff16600a613feb565b8151613045908a614096565b61304f9190613f86565b606082015260675461306c90600160a01b900460ff16600a613feb565b81516130789087614096565b6130829190613f86565b60808201526060810151604082015161309d90612710614096565b6130a79190613f86565b60a0820152608081015160408201516130c290612710614096565b6130cc9190613f86565b8160c0018181525050606b60000160009054906101000a900461ffff1661ffff168160a00151109c50606b60000160029054906101000a900461ffff1661ffff168160a00151119b50606b60000160049054906101000a900461ffff1661ffff168160c00151109a50606b60000160069054906101000a900461ffff1661ffff168160c001511199506064606b60000160009054906101000a900461ffff1661317591906140b5565b61ffff168160a001511098505050613191565b60019a50600198505b5050505050509091929394565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461322a578181101561321d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016104cf565b61322a8484848403612b1b565b50505050565b6001600160a01b0383166132945760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104cf565b6001600160a01b0382166132f65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104cf565b6001600160a01b0383166000908152603360205260409020548181101561336e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016104cf565b6001600160a01b038085166000908152603360205260408082208585039055918516815290812080548492906133a5908490613f6e565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133f191815260200190565b60405180910390a361322a565b60008215801561340c575081155b156134195750600161349d565b5083518351811490811561349b578260005b8281101561346c5786818151811061344557613445614187565b6020026020010151826134589190613f6e565b91508061346481614156565b91505061342b565b5084811115925082801561349757508061271061348b8761270f614096565b6134959190613f86565b105b9250505b505b949350505050565b6040516335ea6a7560e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2600482015260009073057835ad21a177dbdd3090bb1cae03eacf78fc6d906335ea6a75906024016101406040518083038186803b15801561350757600080fd5b505afa15801561351b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353f9190613b67565b50939998505050505050505050565b60006135a3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136209092919063ffffffff16565b805190915015612da957808060200190518101906135c19190613ac4565b612da95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104cf565b606061349d8484600085856001600160a01b0385163b6136825760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104cf565b600080866001600160a01b0316858760405161369e9190613cac565b60006040518083038185875af1925050503d80600081146136db576040519150601f19603f3d011682016040523d82523d6000602084013e6136e0565b606091505b5091509150613497828286606083156136fa575081610ff0565b82511561370a5782518084602001fd5b8160405162461bcd60e51b81526004016104cf9190613ea6565b803561372f816141b3565b919050565b600082601f83011261374557600080fd5b8135602061375a61375583613f4a565b613f19565b80838252828201915082860187848660051b890101111561377a57600080fd5b60005b858110156137a2578135613790816141b3565b8452928401929084019060010161377d565b5090979650505050505050565b600082601f8301126137c057600080fd5b813560206137d061375583613f4a565b80838252828201915082860187848660051b89010111156137f057600080fd5b60005b858110156137a2578135845292840192908401906001016137f3565b600082601f83011261382057600080fd5b813567ffffffffffffffff81111561383a5761383a61419d565b61384d601f8201601f1916602001613f19565b81815284602083860101111561386257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561389157600080fd5b8135610ff0816141b3565b6000602082840312156138ae57600080fd5b8151610ff0816141b3565b600080604083850312156138cc57600080fd5b82356138d7816141b3565b915060208301356138e7816141b3565b809150509250929050565b60008060006060848603121561390757600080fd5b8335613912816141b3565b92506020840135613922816141b3565b929592945050506040919091013590565b6000806040838503121561394657600080fd5b8235613951816141b3565b946020939093013593505050565b60008060008060008060008060008060006101608c8e03121561398157600080fd5b61398a8c613724565b9a5060208c0135995060408c0135985067ffffffffffffffff8060608e013511156139b457600080fd5b6139c48e60608f01358f01613734565b98508060808e013511156139d757600080fd5b6139e78e60808f01358f016137af565b975060a08d0135965060c08d0135955060e08d013594506101008d013593506101208d01359250806101408e01351115613a2057600080fd5b50613a328d6101408e01358e0161380f565b90509295989b509295989b9093969950565b600080600080600080600060e0888a031215613a5f57600080fd5b8735613a6a816141b3565b96506020880135955060408801359450606088013593506080880135925060a0880135915060c088013567ffffffffffffffff811115613aa957600080fd5b613ab58a828b0161380f565b91505092959891949750929550565b600060208284031215613ad657600080fd5b8151610ff0816141cb565b600080600080600060a08688031215613af957600080fd5b8535613b04816141cb565b9450602086013593506040860135925060608601359150608086013567ffffffffffffffff811115613b3557600080fd5b613b418882890161380f565b9150509295509295909350565b600060208284031215613b6057600080fd5b5051919050565b6000806000806000806000806000806101408b8d031215613b8757600080fd5b8a51995060208b0151985060408b0151975060608b0151965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015164ffffffffff81168114613bdd57600080fd5b809150509295989b9194979a5092959850565b600081518084526020808501808196508360051b8101915082860160005b85811015613c38578284038952613c26848351613c80565b98850198935090840190600101613c0e565b5091979650505050505050565b600081518084526020808501945080840160005b83811015613c7557815187529582019590820190600101613c59565b509495945050505050565b60008151808452613c988160208601602086016140ef565b601f01601f19169290920160200192915050565b60008251613cbe8184602087016140ef565b9190910192915050565b6001600160a01b03878116825286166020820152604081018590526060810184905260c060808201819052600090613d0290830185613c80565b905060ff831660a0830152979650505050505050565b6001600160a01b03949094168452602084019290925260ff908116604084015216606082015260800190565b6001600160a01b038b8116825260208083018c9052604083018b9052610140606084018190528a519084018190526000926101608501928c810192855b81811015613d9f578451841686529482019493820193600101613d81565b50505050508281036080840152613db6818a613c45565b60a0840198909852505060c081019490945260e08401929092526101008301526101209091015295945050505050565b60018060a01b038516815283602082015282604082015260a060608201526000613e1360a0830184613c80565b82810360808401526002815261060f60f31b60208201526040810191505095945050505050565b604081526000613e4d6040830185613bf0565b8281036020840152613e5f8185613bf0565b95945050505050565b606081526000613e7b6060830186613bf0565b8281036020840152613e8d8186613bf0565b91505060018060a01b0383166040830152949350505050565b602081526000610ff06020830184613c80565b6020808252600f908201526e37b7363c903932b130b630b731b2b960891b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f4257613f4261419d565b604052919050565b600067ffffffffffffffff821115613f6457613f6461419d565b5060051b60200190565b60008219821115613f8157613f81614171565b500190565b600082613fa357634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115613fe3578160001904821115613fc957613fc9614171565b80851615613fd657918102915b93841c9390800290613fad565b509250929050565b6000610ff060ff84168360008261400457506001610363565b8161401157506000610363565b816001811461402757600281146140315761404d565b6001915050610363565b60ff84111561404257614042614171565b50506001821b610363565b5060208310610133831016604e8410600b8410161715614070575081810a610363565b61407a8383613fa8565b806000190482111561408e5761408e614171565b029392505050565b60008160001904831182151516156140b0576140b0614171565b500290565b600061ffff838116908316818110156140d0576140d0614171565b039392505050565b6000828210156140ea576140ea614171565b500390565b60005b8381101561410a5781810151838201526020016140f2565b8381111561322a5750506000910152565b600181811c9082168061412f57607f821691505b6020821081141561415057634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561416a5761416a614171565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146141c857600080fd5b50565b80151581146141c857600080fdfea264697066735822122060404c8715140903c5622b9b1357c3c9d3ebf9957808a5544217ae458286ac1664736f6c63430008060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.